微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Angular2 中使用 @Input 装饰器初始化属性的正确方法是什么?

如何解决在 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 举报,一经查实,本站将立刻删除。