Version: "angular2": "2.0.0-beta.6"
I would like to implement a two way binding inside a parent/child component case.
On my child component, I'm using two-way binding to display text while editing.
Child component (InputTestComponent [selector:'input-test']
):
<form (ngSubmit)="onSubmit()" #testform="ngForm"> {{name}} <textarea #textarea [(ngModel)]="name" ngControl="name" name="name"></textarea> <button type="submit">Go</button> </form>
Then, I would like to propagate this change to his parent component. I tried with [(name)]="name"
with no success.
Parent component:
<div> {{name}} <input-test [(name)]="name"></input-test> </div>
Code sample
What the easiest way to do it (less verbose) ?
Angular v2+ supports two-way data binding using ngModel directive and also by having getter and setter methods.
The <parent-component> serves as the context for the <child-component> . @Input() and @Output() give a child component a way to communicate with its parent component. @Input() lets a parent component update data in the child component. Conversely, @Output() lets the child send data to a parent component.
For 2-way binding use @Input()
and @Output()
. The names should be propName
and propNameChange
to allow the shorthand binding syntax [(propName)]="someModel"
otherwise you'd need the longer version [propName]="someModel" (propNameOtherOutputName)="propName=$event;propNameOtherOutputName.emit($event)"
@Component{ ... template: ` <textarea #textarea [(ngModel)]="name" (ngModelChange)="nameChange.emit($event)" ngControl="name" name="name"></textarea> `}) export class InputTestComponent { @Output() nameChange:EventEmitter<String> = new EventEmitter<String>(); @Input() name:string; }
You can setup two-way data binding between parent and child component in the following ways:
<app-child [(counter)]="counter"></app-child> <app-child [counter]="counter" (counterChange)="counter=$event"></app-child> <app-child [counter]="counter" (counterChange)="onCounterChange($event)"></app-child>
According to Angular - Template Syntax - Two-way binding:
Angular offers a special two-way data binding syntax for this purpose, [(x)]. The [(x)] syntax combines the brackets of property binding, [x], with the parentheses of event binding, (x).
<app-child [(counter)]="counter"></app-child>
The [(x)] syntax is easy to demonstrate when the element has a settable property called x and a corresponding event named xChange.
@Input() counter: number; @Output() counterChange = new EventEmitter<number>();
The two-way binding syntax is really just syntactic sugar for a property binding and an event binding. Angular desugars the ChildComponent binding into this:
<app-child [counter]="counter" (counterChange)="counter=$event"></app-child>
Example: https://stackblitz.com/edit/angular-two-way-data-binding-between-parent-and-child-component?file=src%2Fapp%2Fapp.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-root', template: ` <div style="background-color: red; padding: 10px;"> <div>{{counter}}</div> <button (click)="increment()">increment from parent</button> <app-child [(counter)]="counter"></app-child> <app-child [counter]="counter" (counterChange)="counter=$event"></app-child> <app-child [counter]="counter" (counterChange)="onCounterChange($event)"></app-child> </div> ` }) export class AppComponent { counter = 0; increment() { this.counter++; } onCounterChange(counter: number) { this.counter = counter; } } @Component({ selector: 'app-child', template: ` <div style="background-color: green; padding: 10px; margin: 10px;"> <div>{{counter}}</div> <button (click)="increment()">increment from child</button> </div> `, }) export class ChildComponent { @Input() counter: number; @Output() counterChange = new EventEmitter<number>(); constructor() { } increment() { this.counterChange.emit(++this.counter); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With