web-dev-qa-db-ja.com

ディレクティブで入力値が変更されたことを検出する

入力のvalueがディレクティブで変更されたことを検出しようとしています。次のディレクティブがあります。

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');
    }
}

このディレクティブの問題は、値がプログラム的に変更されたときではなく、入力があるときのみ検出することです。私はreaciveフォームを使用し、時々patchValue()関数で値を設定します。変更機能がトリガーされるようにするにはどうすればよいですか?

29
ncohen

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

45
Teddy Sterne

この結果を使用するより良い方法があります。たとえば、*ngIf Angular source code で使用されます。

@Input()setterを組み合わせることができます。入力が変更されると、セッターが再度呼び出されます。

@Input() set numberOfWheels(wheels: number) {
  if(wheels === 2) {
    console.log("It's a bike!");
  }
  else if(wheels === 4) {
    console.log("It's a car!");
  }
  else {
    console.log("I don't know what it is :(");
  }
}

以前の値をDirectiveプロパティに保存して後で使用し、新しい値と比較することができます。

private previousValue: any = null;

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

HostListenerを使用することもできます。 HostListenerの詳細については、 このリンク をご覧ください。これがコードです。

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');
    }

}
2
Tushar Ghosh