Angular2 two-way data binding
You can do this by attaching to the events on the input field and updating the internal value as is done in this example:
http://plnkr.co/edit/lOFzuWtUMq1hCnrm9tGA?p=preview
Create a component that has an internal attribute that holds the label this.label
and a callback changeLabel
that expects an event object
@Component({
selector: 'app',
templateUrl: 'bound.html'
})
class App {
label: string;
constructor() {
this.label = 'default label'
}
changeLabel(event) {
this.label = event.target.value;
}
}
bootstrap(App);
The create your template and attach the callback to the appropriate event (you could attach it to the keypress
event but then you might need a timeout. I attached it to the change
event for simplicity (which means you might need to tab off the input to see the update).
<label for="myinput">{{label}}</label>
<input id="myinput" type="text"/>
<p></p>You can change the label above by typing something below</p>
<label for="labeltext">New Label Text</label>
<input type="text" id="labeltext" (change)="changeLabel($event)"/>
Yes there is two-way binding in angular2. See here: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngModel
So, how to use it in custom components?
What I like to do is something this:
private currentSelectedItem: MachineItem;
@Output() selectedItemChange: EventEmitter<MachineItem> = new EventEmitter<MachineItem>();
@Input() set selectedItem(machineItem: MachineItem) {
this.currentSelectedItem = machineItem;
this.selectedItemChange.emit(machineItem);
}
get selectedItem(): MachineItem {
return this.currentSelectedItem;
}
And use it like
<admin-item-list [(selectedItem)]="selectedItem"></admin-item-list>
You can also emit the new value where it is actually changed. But I find it quite convenient to do that gloabaly in a setter method and don't have to bother e.g. when I bind it directly to my view.
You can now simply do this by using ngModel using the following syntax:
<input [(ngModel)]="myProp" />
The combination of the square and round brackets means "two-way binding".
Please see the plunk here
Note - scroll down the answer for ng-model binding
You could actually do that, just that you need to invoke internal changelistener tick (similar to digest) to update binding in the zone, You can just add a (keyup)
event for that. Similarly you could use directive bindings as well with properties
dictionary of component settings.
Example:-
<input #label (keyup)>
<!-- variable #label represented as the element itself and accessible as property on controller instance
You can even bind keyup to a function or another another function and pass value from the label property-->
Display as:
<p>{{label.value}}</P>
Parent Component has a textbox and a label.
import { Component, bootstrap} from '@angular/core';
import {Display} from 'display';
@Component({
selector: 'my-app',
template: `<p><b>Parent Component:</b><p><input #label (keyup) (change)="handleChange(label.value)">
<p>{{label.value}}</P> <display [text]="label"></display></p></p>`,
directives: [Display]
})
class MainComponent {
label: any;
constructor() {
}
handleChange(label){
this.label = label;
console.log(this.label);
}
}
Now displaying it in child component as well:
@Component({
selector: 'edit',
template: `<p><b>Child Component:</b></p>{{text.value}}`
})
export class Edit {
@Input() text:any;
}
Demo
Update - ng-model for 2-way binding
Though Angular2 is one-time bound by default, ngModel
sugar has been introduced to achieve 2-way binding. With that you could do for instance:
<input ngControl="name" [(ngModel)]="name">
Here usage of square brackets ([..]
) suggests the property binding and round brackets ((..)
) for event binding. Basically when you use ng-model
, you are enabling both the bindings ngModel
is more of an event. Behind the scenes it creates an observable event(with EventEmitter
) to track the value
changes in the bound element and update the bound property respectively.
For example:-
Include formDirectives:
import {FORM_DIRECTIVES} from '@angular/common';
and with form
<form (ngSubmit)="onSubmit()" let-f="form">
<input ngControl="name" [(ngModel)]="name">
<button>Click me and check console</button>
</form>
without form
<input [(ngModel)]="name">
<button (click)="onSubmit()">Click me and check console</button>
not necessary anymore
include formDirectives dependency in view annotation.
@Component({
template: .....,
directives: [FORM_DIRECTIVES]
})
Demo
Also read the nice write up from Victor Savkin on Two-way binding in angular2 by creating the ng-model event and how it works.