检测指令中的输入值何时更改

Detect when input value changed in directive

我正在尝试检测输入的 何时在指令中更改。我有以下指令:

    import { ElementRef, Directive, Renderer} from '@angular/core';

    @Directive({
        selector: '[number]',
        host: {"(input)": 'onInputChange($event)'}
    })

    export class Number {

        constructor(private element: ElementRef, private renderer: Renderer){

        }
        onInputChange(event){
            console.log('test');
        }
    }

此指令中的问题是它仅在有输入时检测,而不是在值以编程方式更改时检测。我使用反应形式,有时我使用 patchValue() 函数设置值。我怎样才能触发更改功能?

您需要输入 input 的 属性,然后使用 ngOnChanges 挂钩来告知输入 属性 何时更改。

@Directive({
    selector: '[number]'
})
export class NumberDirective implements OnChanges {
    @Input() public number: any;
    @Input() public input: any;

    ngOnChanges(changes: SimpleChanges){
      if(changes.input){
        console.log('input changed');
      }
    }
}

Plunkr

Stackblitz

您也可以使用 HostListener。有关 HostListener 的更多信息,您可以浏览 this link。这是代码。

import {Directive, ElementRef, HostListener} from '@angular/core';


@Directive({
       selector: '[number]'
 })

export class NumberDirective {

    @Input() public number: any;
    @Input() public input: any;

    constructor(private el: ElementRef) {}

    @HostListener('change') ngOnChanges() {
        console.log('test');
    }

}

有一种更好的方法来检测 Input 属性 何时发生变化,它被认为是最佳实践,它也用于 *ngIf implementation

你只需要在 Input() 之后推迟关键字 set,这样你就可以将 @Input() 装饰器与 setter 结合起来,它会被调用所有值变化的倍数。

_rows: number;
@Input() set rows(value: number) {
  if (this.value < 0) {
    console.error('The number of rows must be positive');
    this._rows = 2;
    return;
  }
 
  this._rows = value;
}

如果要将新值与先前值进行比较,必须将变量存储在 class 属性 中,并在第二次调用该方法时检索它:

private previousValue: any = T;

@Input() set myInputName(value: T) {
  console.log(`Previous value was: ${this.previousValue}`);
  console.log(`New value is: ${value}`);
  this.previousValue = value;  
}

截至 Angular 9+ 我可以验证下面的代码片段是正确的解决方案。出于多种原因,最好尽可能避免 ngOnChanges 并改用正确的主机侦听器事件。下面的示例将获取 keyup 上的当前输入值。您可以根据输入指令的需要轻松自定义此代码段。

  @Directive({
      selector: '[appMyDirective]',
  })
  export class MyDirective {
    // Add whatever event you want to track here
    @HostListener('keyup', ['$event']) public onKeyup(event: KeyboardEvent): void {
      const value = (event.target as HTMLInputElement).value;
      console.log(value);
    }
  }