Fuzzley Fuzzley - 1 year ago 74
TypeScript Question

Listen to Changes on an Object's field in Angular2/Typescript

In Angular2/Typescript, is it possible to "observe" an object's field for changes.

For example, say I have a class

Person
with fields
firstName
,
lastName
, and
fullName
. Is it possible to automatically update
fullName
whenever either
firstName
or
lastName
changes?

Something like this:

export class Person {
firstName: string= '';
lastName: string = '';
fullName: string = '';

constructor(firstName: string, lastName: string) {
this.firstName.onChange(() => { this.updateFullName(); });
this.lastName.onChange(() => { this.updateFullName(); });

this.firstName = firstName;
this.lastName = lastName;
}

updateFullName() {
this.fullName = `${this.firstName} ${this.lastName}`;
}
}

Answer Source

First approach

You could leverage TypeScript setters / getters as described below to synchronize fullName with firstName and lastName:

get lastName() {
  return this._lastName;
}

set lastName(lastName:string) {
  this._lastName = lastName;
  this.fullName = this._firstName + ' ' + this._lastName;
}

get firstName() {
  return this._firstName;
}

set firstName(firstName:string) {
  this._firstName = firstName;
  this.fullName = this._firstName + ' ' + this._lastName;
}

This way when setting lastName or firstName, fullName is automatically updated:

var p = new Person();
p.lastName = 'last';
p.firstName = 'first';
console.log(p.fullName); // print 'first last'

Second approach

Angular2 by default doesn't allow to define change of properties within objects. It only detects updates of at references. I mean if the reference (or value for primitive types) of a bound property is updated.

That bien said, Angular2 allows to plugin your own strategy using the ngDoCheck hook method.

In it you can leverage the KeyValueDiffers class (to be injected) to detect updates in specific objects.

See this link for more details:

Here is a sample:

@Component({
  selector: 'my-component',
  (...)
}) 
export class MyComponent implements DoCheck {
  @Input() person: Person;
  differ: any;

  constructor(differs:  KeyValueDiffers) {
    this.differ = differs.find([]).create(null);
  }

  ngDoCheck() {
    var changes = this.differ.diff(this.person);

    if (changes) {
      changes.forEachChangedItem((elt) => {
        if (elt.key === 'firstName' || elt.key === 'lastName' ) {
          this.person.fullName = this.person.firstName + ' ' + this.person.lastName;
        }
      });
    }
  }
}

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

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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download