Scottie
Scottie

Reputation: 11308

Angular 2 two-way component binding doesn't call parent ngOnChange

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?

Upvotes: 1

Views: 2901

Answers (1)

Mark Rajcok
Mark Rajcok

Reputation: 364707

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

Upvotes: 3

Related Questions