detect change of nested property for component input

后端 未结 2 1080
谎友^
谎友^ 2020-12-03 23:47

In a simplified way I have an Angular2 Component and an input object like this:

class MyObject{
 Prop1:string;
 Prop2:Number;
}  

@Component() 
export class         


        
相关标签:
2条回答
  • 2020-12-03 23:57

    In fact, by default Angular2 detects changes when object reference is updated not its content. But this default behavior can be changed by using the DoCheck interface.

    In your case (detecting that a property was updated into the myObject object, you could use the following approach:

    @Component({
      selector: 'my-component',
      (...)
    }) 
    export class MyComponent implements DoCheck {
      @Input() myObject: MyObject;
      differ: any;
    
      constructor(differs:  KeyValueDiffers) {
        this.differ = differs.find([]).create(null);
      }
    
      ngDoCheck() {
        var changes = this.differ.diff(this.myObject);
    
        if (changes) {
          changes.forEachChangedItem((elt) => {
            if (elt.key === 'prop1') {
              this.doSomethingIfProp1Change();
            }
          });
        }
      }
    
      doSomethingIfProp1Change() {
        console.log('doSomethingIfProp1Change');
      }
    }
    

    When the value of the prop1 property is updated, the doSomethingIfProp1Change method is called.

    See this plunkr: http://plnkr.co/edit/uvOKMXQa9Ik8EiIhb60Y?p=preview.

    0 讨论(0)
  • 2020-12-03 23:58

    You can use observables to support notification of subscribers. Angular itself doesn't provide support for observing changes of internal object state.

    class MyObject{
      constructor() {
        this.prop1Change$ = new Observable(observer => 
            this._prop1Observer = observer).share(); // share() allows multiple subscribers
    
        this.prop2Change$ = new Observable(observer =>
            this._prop2Observer = observer).share();
            console.debug(this._prop2Observer);
      }
    
      prop1Change$: Observable<string>;
      private _prop1Observer: Observer;
      _prop1:string;
      get prop1():string { return this._prop1 };
      set prop1(value:string) {
        this._prop1 = value;
        this._prop1Observer && this._prop1Observer.next(value);
      }
    
      prop1Change$: Observable<number>;
      private _prop2Observer: Observer;
      _prop2:Number;
      get prop2():number { return this._prop2 };
      set prop2(value:number) {
        this._prop2 = value;
        console.debug(this);
        this._prop2Observer && this._prop2Observer.next(value);
      }
    }
    

    This code could be shortened by using Subject but Observable should be favored over Subject.

    @Component() 
    export class MyComponent{
      @Input() myObject: MyObject;
    
      count2:number;
    
      DoSomethingIfProp1Change(){
        console.log(myObject.prop1);
      }
    
      ngOnChanges(changes: {[propName: string]: SimpleChange}) {
        console.log('changes');
        if(changes['myObject']) {
          if(this.prop2Subscription) {
            this.prop2Subscription.unsubscribe();
          }
          this.prop2Subscription = this.myObject.prop2Change$.subscribe(value => {
            this.count2 = value;
            console.log('count2: ' + value);
          });
          // same for `prop2`
        }
      }
    }
    

    Plunker example

    See also Delegation: EventEmitter or Observable in Angular2

    0 讨论(0)
提交回复
热议问题