简体   繁体   中英

Observable of Component Attribute Changes in Angular2

When creating a component in angular 2 that has inputs attributes via @Input, how can I get an observable from the changes made to that attribute @Input (not to be confused with user form input).

export class ExampleComponent implement OnChanges{
    @Input() userObject: User;

    ngOnChanges(changes: any): void{
        // Validate that its the 'userObject' property first
        this.doStuff()
    }
}

In practice, I would like to merge the Observable changes of the userObject with the Observable changes of other things to have a fluent change reaction pattern.

export class ExampleComponent implement OnChanges{
    @Input() userObject: User;

    constructor():{
        userObject.valueChanges.subscribe(x=>{ this.doStuff() });
    }
}

I found out the that BehaviorSubject class enables this scenario the best. Instead of creating a separate backend field, you can use the BehaviorSubject's getValue function to peak at the current value. Then use the backing BehaviorSubject to view as an observable for changes.

export class ExampleComponent{
    private _userObject: BehaviorSubject<User> = new BehaviorSubject<User>(null);

    @Input()
    set userObject(value: User): { this._userObject.next(value); }
    get userObject(): User { return this._userObject.getValue(); }
}

Try usings a get and a set, valueChanges() below will fire on being set.

  private _userObject: User;
  @Input()
  set userObject(userObject: User) {
    this._userObject = userObject;
    this.valueChanges();
  }
  get userObject(): User {
    return this._userObject;
  }

With an Observable:

  private userObjectChange = new Subject<User>();
  userObjectChange$ = this.userObjectChange.asObservable();

  private _userObject: User;
  @Input()
  set userObject(userObject: User) {
    this.userObjectChange.next(userObject);
    this._userObject = userObject;
  }
  get userObject(): User {
    return this._userObject;
  }

To subscribe:

this.newQuote.subscribe(user => {...})

You can use subject for this:

export class ExampleComponent {
    @Input() set userObject(userObject: User) {
       this.userObject$.next(userObject);
    }

    private userObject$ = new Subject<User>();

    constructor():{
        this.userObject$.subscribe(x=>{ this.doStuff() });
    }
}

The best way to check the change of an input is actually by using the ngOnChanges life cycle.

ngOnChanges(changes: { [propertyName: string]: SimpleChange }) {
  const changedInputs = Object.keys(changes);
  // Only update the userObject if the inputs changed, to avoid unnecessary DOM operations.
  if (changedInputs.indexOf('userObject') != -1) {
  // do something
  }    
}

Reference: https://github.com/angular/material2/blob/master/src/lib/icon/icon.ts#L143

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM