Angular 2 ngModel in child component updates parent component property

We can use the [(x)] syntax in the parent template to achieve two-way databinding with the child. If we create an Output property with the name xChange, Angular will automatically update the parent property. We do need to emit() an event whenever the child changes the value however:

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

@Component({
    selector: 'child',
    template: `
        <p>Child sharedVar: {{sharedVar}}</p>
        <input [ngModel]="sharedVar" (ngModelChange)="change($event)">
    `
})
export class ChildComponent {
    @Input() sharedVar: string;
    @Output() sharedVarChange = new EventEmitter();
    change(newValue) {
      console.log('newvalue', newValue)
      this.sharedVar = newValue;
      this.sharedVarChange.emit(newValue);
    }
}

@Component({
    selector: 'parent',
    template: `
        <div>Parent sharedVarParent: {{sharedVarParent}}</div>
        <child [(sharedVar)]="sharedVarParent"></child>
    `,
    directives: [ChildComponent]
})
export class ParentComponent {
    sharedVarParent ='hello';
    constructor() { console.clear(); }
}

Plunker

I used sharedVarParent in the ParentComponent just to demonstrate that the names don't have to be the same in the parent and child.


And if you want to have multiple two-way databindings in the same component, you can do

export class ComponentName {
    @Input() public first: string = '';
    @Input() public second: string = '';
    @Output() public firstChange = new EventEmitter();
    @Output() public secondChange = new EventEmitter();

    public functionName1(first: string): void {
        this.first = first;
        this.firstChange.emit(first);
    }

    public functionName2(second: string): void {
        this.second = second;
        this.secondChange.emit(second);
    }
}

When input and output are named 'x' and 'xChange', it detects them automatically in the parent belonging together.

I think this is actually a better practice than the one in the accepted answer, because here it makes immediately clear how the names are related.


You could set up event emitter communication (outputs) from child to parent. For example like this:

@Component({
    selector: 'child',
    template: `
        <p>Child: {{sharedVar}}</p>
        <input [(ngModel)]="sharedVar" (ngModelChange)="change()">
    `
})
export class ChildComponent {
    @Output() onChange = new EventEmitter();
    sharedVar: string;
    change() {
        this.onChange.emit({value: this.sharedVar});
    }
}

and the in parent component:

@Component({
    selector: 'parent',
    template: `
        <h1>{{sharedVar}}</h1>
        <child (onChange)="sharedVar = $event.value"></child>
    `,
    directives: [ChildComponent]
})
export class ParentComponent {
    sharedVar: string;
    constructor() {

    }
}

Demo: http://plnkr.co/edit/T2KH4nGKPSy6GEvbF1Nb?p=info