4
votes

I wanted to extend the app from [Angular2's Tutorial][1] by having a grandchild component , power-select, called from the HeroDetailComponent:

  selector: 'my-hero-detail',
  template: `
    <div *ngIf="hero">
      <h2>{{hero.name}} details!</h2>
      <div><label>id: </label>{{hero.id}}</div>
      <div> 
        <label>name: </label>
        <input [(ngModel)]="hero.name" placeholder="name"/>
        <power-select [(power)]="hero.power"></power-select>
      </div>
    </div>
  `,
  directives: [PowerSelectComponent],
  inputs: ['hero']

When I pass in the hero.power as an object, changes get reflected to the parent/grandparent.

http://plnkr.co/edit/UfMStWU5fEywvovpSIg1?p=preview

However if I try to pass hero.power as a string the changes do not get reflected unless I use an @Ouput eventemitter.

http://plnkr.co/edit/p9YcfGudIgSbGPp1xrlw?p=preview (provided by: zoechi)

The question is, why do I need the @Output eventemitter when I pass a string and not when I pass an object?

1

1 Answers

5
votes

The difference is that object properties are mutable while a string is not (like all other primitive types boolean, number, symbol, null, and undefined https://developer.mozilla.org/de/docs/Web/JavaScript/Datenstrukturen).

An object gets passes as reference, therefore your grandparent, parent, child (wherever you pass it) have a reference to the same object while a string is passed as copy.
If you pass a string around everyone gets a copy which is not related to the source at all (except that it has the same value).

You might argue that the property of the object is also a string. If the string property of the object is modified, a different string is set as value, but because nothing references the string directly but rather through the object reference, when they access the string property, they get the new value.