I am trying to make something work on angular2 and I am unable to find something about this behavior.
I have an application that implements a custom component like this one :
import {Component,Input} from 'angular2/core'
@Component({
selector:'my-comp',
template:`<input type="text" style="text-align:center; [(ngModel)]="inputText"> <p>{{inputText}}</p>`
})
export class MyComp{
@Input() inputText : string;
}
And I am trying to do a bidirectional databinding on my inputText
variable from my component like this:
<my-comp [(inputText)]="testString"></my-comp>
Where the testString
is a variable defined in the MyApp.ts
which contains a string. I want my testString
variable to be modified when my inputText
is modified by the user.
Here is a Plunker with a simple sample code : https://plnkr.co/edit/zQiCQ3hxSSjCmhWJMJph?p=preview
Is there a way to make this works simply ? Do I have to implements an Angular2 class on my custom components and overload functions in order to make this works like an ngModel
? Do i necessarily have to create a inputTextChanged
variable of EventEmitter
type that emit my data when it's changed and do something like this :
<my-comp [inputText]="testString" (inputTextChanged)="testString = $event;"></my-comp>
Thank you in advance.
Two-way data binding refers to sharing data between a component class and its template. If you change data in one place, it will automatically reflate at the other end. For example, if you change the value of the input box, then it will also update the value of the attached property in a component class.
For two-way data binding to work, the @Output() property must use the pattern, inputChange , where input is the name of the @Input() property. For example, if the @Input() property is size , the @Output() property must be sizeChange .
The two-way data binding in Angular is used to display information to the end user and allows the end user to make changes to the underlying data using the UI. This makes a two-way connection between the view (the template) and the component class.
AngularJS provides two types of Data Binding: One-way data binding. Two-way data binding.
This is explained in the Template Syntax doc, in the Two-Way Binding with NgModel section:
<input [(ngModel)]="currentHero.firstName">
Internally, Angular maps the term,
ngModel
, to anngModel
input property and anngModelChange
output property. That’s a specific example of a more general pattern in which it matches[(x)]
to anx
input property for Property Binding and anxChange
output property for Event Binding.We can write our own two-way binding directive/component that follows this pattern if we're ever in the mood to do so.
Note also that [(x)]
is just syntactic sugar for a property binding and an event binding:
[x]="someParentProperty" (xChange)="someParentProperty=$event"
In your case, you want
<my-comp [(inputText)]="testString"></my-comp>
so your component must have an inputText
input property and an inputTextChange
output property (which is an EventEmitter
).
export class MyComp {
@Input() inputText: string;
@Output() inputTextChange: EventEmitter<string> = new EventEmitter();
}
To notify the parent of changes, whenever your component changes the value of inputText
, emit an event:
inputTextChange.emit(newValue);
In your scenario, the MyComp component binds input property inputText
using the [(x)]
format to ngModel, so you used event binding (ngModelChange)
to be notified of changes, and in that event handler you notified the parent component of the change.
In other scenarios where ngModel isn't used, the important thing is to emit()
an event whenever the value of property inputText
changes in the MyComp component.
I'll combine @pixelbits and @Günter Zöchbauer answers and comments to make a clear answer on my question if someone in the future is searching for this.
To make bidirectional data binding works on custom variables you need to creates your component based on the following.
MyComp.ts file :
import {Component,Input,Output,EventEmitter} from 'angular2/core'
@Component({
selector:'my-comp',
templateUrl:`<input type="text" style="text-align:center;"
[ngModel]="inputText" (ngModelChange)="inputText=$event;inputTextChange.emit($event);">`
})
export class MyComp{
@Input() inputText : string;
@Output() inputTextChange = new EventEmitter();
}
MyApp.ts file:
import {Component} from 'angular2/core'
import {MyComp} from './MyComp'
@Component({
selector:'my-app',
templateUrl:`<h1>Bidirectionnal Binding test </h1>
<my-comp [(inputText)]="testString"></my-comp><p>
<b>My Test String :</b> {{testString}}</p>`,
directives:[MyComp]
})
export class MyApp{
testString : string;
constructor(){
this.testString = "This is a test string";
}
}
There the bidirectional data binding to the inputText
variable works correctly.
You can comment the answer for a more beautiful or simpler way to implement this code.
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