[Angular Tutorial] Create your own two-way data binding

Alain Chautard
Angular Training
Published in
2 min readAug 8, 2017

--

You’re probably familiar with [(ngModel)] and its world-famous “banana in a box” syntax. In this post, I’m going to explain how ngModel actually works, which will allow us to replicate its behavior in order to implement our own two-way data binding.

In the end, we‘re going to create a component that takes a message as a parameter, and that message will be our component model. We would use that component as follows:

<example-component [(message)]="title"></example-component>

Highlighted in the above code is the two-way data binding we’re looking to implement.

First, let’s dissect the “banana in the box” syntax applied to ngModel. Here is the syntax that we all know about:

<input [(ngModel)]="title" type="text">

What’s interesting is that the [()] turns out to be syntactic sugar for the following:

<input [ngModel]="title" (ngModelChange)="title= $event" type="text">

The above code is definitely more verbose but it makes perfect sense when you think about it. A two-way data-binding is really… two one-way data-bindings, right?

Now the real secret that the above example unveils is the use of the Change suffix. Let’s apply this trick to our own example component.

First let’s create a simple component with a @Input to have a one-way data binding:

export class TwoWayDataBindingExampleComponent  {

messageValue : string;

@Input()
get message(){
return this.messageValue;
}

set message(val) {
this.messageValue = val;
}
}

There are two important things to note here. First I use a property messageValue to store the actual message. Then I expose it as message, so that I can use TypeScript getters and setters to read and set the value of messageValue.

This is a key part of the technique since our setter will have to do some more work to actually notify other components of any model update.

Here is how we implement the second one-way data-binding:

export class TwoWayDataBindingExampleComponent  {

messageValue : string;

@Output()
messageChange = new EventEmitter<string>();

@Input()
get message(){
return this.messageValue;
}

set message(val) {
this.messageValue = val;
this.messageChange.emit(this.messageValue);
}
}

Now we have everything in place. Both the getter and setter use messageValue to read / update our data model, but the setter also notifies the rest of the world by emitting an event.

As a result, we can now have a two-way data binding applied to that component with the following syntax:

<example-component [(message)]="title"></example-component>

Wasn’t that easy? Well, it sure is once we know the trick to get there. Now you can implement two-way data-bindings in your own components!

My Name is Alain Chautard. I am the founding consultant and trainer at Angular Training where I help web development teams learn and become fluent with Angular. Check us out @AngularTraining!

If you enjoyed this Angular tutorial, please recommend and share it! Thanks for your time.

--

--