1

I have created a plunker here:

http://plnkr.co/edit/8bwqkYQ6tqrpGwHT588y?p=preview

that shows the issue.

Basically, I have 2 components. The first component has a 2-way binding of a property to the child component.

My parent component is:

import { Component, Input, Output, EventEmitter } from '@angular/core'
import { ChildComponent } from "./childComponent"

@Component({
    selector: 'parentComponent',
    template: `
    <div>
      <a href="#" (click)="selectedId = 0">Reset</a><br>
      <div>Parent SelectedId: {{selectedId}}</div>
      <childComponent [(selectedId)]="selectedId"></childComponent>
    </div>
  `,
  directives: [ChildComponent]
})

export class ParentComponent {
  @Input() selectedId: number;

    ngOnChanges(changes) {
      console.log("Parent changes called!");
    }
}

and my child component:

import { Component, Input, Output, EventEmitter } from '@angular/core'

@Component({
    selector: 'childComponent',
    template: `
    <div>
      <div>Child SelectedId: {{selectedId}}</div> 
    </div>
  `,
  directives: []
})

export class ChildComponent {
  @Input() selectedId: number;
  @Output() selectedIdChange: EventEmitter<number> = new EventEmitter<number>();

    constructor() {
      setTimeout(() => {
        this.selectedId = 100;
        this.selectedIdChange.emit(this.selectedId);
       }, 2000);
    }

    ngOnChanges(changes) {
      console.log("Child changes called!");
    }
}

In the child, I set a timeout to change the value of selectedId programmatically after 2 seconds, then emit the value back to the parent.

This all works great, except for one thing... the ngOnChange of the parent is only being called once.

I would think that the parent would very much like to know if the child has changed the value, or else what is the point of 2 way binding??

What am I missing here?

Scottie
  • 11,050
  • 19
  • 68
  • 109

1 Answers1

3

The ngOnChange of the parent will only be called if App's selectedId changes, since that's what ParentComponent's input property is bound to.

If you want the parent to be notified of changes made in the child, bind to the xChange event (where x is the name of the input property) – i.e., break up the property and event bindings:

<childComponent [selectedId]="selectedId" (selectedIdChange)="changed($event)"></childComponent>
changed(newValue) {
  console.log('newValue', newValue);
  this.selectedId = newValue;
}

Plunker

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • @Scottie, well, sometimes you just want the parent (e.g., parent view) to update, and you don't need to be notified because you don't need to execute any logic when the child makes a change. And you are correct, events emitted by EventEmitter don't bubble. If you want multiple components to be notified of a single change, an Observable or a Subject in a shared service is the recommended approach. – Mark Rajcok Jul 16 '16 at 04:08