如何解决在 Angular2 中使用 @Input 装饰器初始化属性的正确方法是什么?
我已经创建了一个 angular 组件来处理我的材料自动完成以选择一个动作。我将来自父组件的 Action[] 传递给它。自动完成功能正常,但我的显示名称功能不起作用。经过一番挖掘,我得到“TypeError:无法读取未定义的属性‘过滤器’”我发现这是因为在我的 displayName 函数中 this.actions 是一个空数组。我觉得 displayName 函数中的 this.actions 卡住了初始值,并且在组件加载输入值时不会更新。我知道我的 actions 属性不为空,因为它与自动完成组件一起按预期工作。是否有正确的方法来初始化我的操作属性,以便它与我的 displayName() 一起使用?
import {Component,Input} from '@angular/core';
import {ControlValueAccessor,FormControl,NG_VALUE_ACCESSOR} from '@angular/forms';
import {Action} from '../../../../Interfaces/action';
import {Observable} from 'rxjs';
import {map,startWith} from 'rxjs/operators';
@Component({
selector: 'app-input-action-typeahead',templateUrl: './input-action-typeahead.component.html',styleUrls: ['./input-action-typeahead.component.scss'],providers: [{
provide: NG_VALUE_ACCESSOR,useExisting: InputActionTypeaheadComponent,multi: true
}]
})
export class InputActionTypeaheadComponent implements ControlValueAccessor {
@input() actions: Action[] = [];
filteredActions: Observable<Action[]>;
actionCtrl = new FormControl();
constructor() {
this.filteredActions = this.actionCtrl.valueChanges.pipe(
startWith(''),map(value => typeof value === 'string' ? value : value.name),map(action => action ? this._filter(action) : this.actions.slice())
);
}
private _filter(value: string): Action[] {
const filterValue = value.toLowerCase();
return this.actions.filter(action => action.name.toLowerCase().indexOf(filterValue) !== -1);
}
registerOnChange(fn: any): void {
this.actionCtrl.valueChanges.subscribe(fn);
}
registerOnTouched(fn: any): void {
}
writeValue(obj: Action): void {
}
displayName(id: number): string {
if (!id) {
return '';
}
return this.actions.filter(action => action.id === id)[0].name;
}
clear(): void {
this.actionCtrl.setValue('');
}
}
解决方法
我怀疑您可能在设置 actions
变量值之前尝试访问它。有几种方法可以解决这个问题,
方法一
在尝试读取 actions
之前检查它是否有值。
displayName(id: number): string {
if(!!id && !!this.actions){
return this.actions.filter(action => action.id === id)[0].name;
}
return '';
}
方法 2
每次运行更改检测时,都会调用您的函数 displayName
。它增加了非常小的性能开销。为了避免这种情况,您可以在操作的 setter 上计算 displayName,因此它不是每次移动鼠标时都会调用的函数。这是更多的代码,但更高效。
_actions: [];
get actions(): []{
return this._actions;
}
set actions(value: []) {
this._actions= value;
this.updateDisplayName();
}
updateDisplayName(actions: []): void{
// use your actions variable here to compute the display name.
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。