Data binding is one of the most important concepts in a JS framework. Data binding is the reflection of logic or variable in a model to the view of an app. Whenever the variable changes the view must update the DOM to reflect the new changes. Angular the most popular JS framework in the world implemented data binding so carefully and intelligently to become one of its most powerful feature to date. There are other features like

CD (Change Detection)

DI (Dependency Injection)

Modular System

but data binding remains the SUPER feature. In this post, we will look deep into Angular’s data binding mechanism. Read on.

Tip: Use tools like Bit (GitHub) to easily share your NG components between your applications, develop and sync changes from any project, stay in sync and build faster together as a team. Give it a try.

NG components in your Bit collection: share, use and develop anywhere

Template Expression {{}}

This is the one-way binding of a component’s property to the template of the component. So, when the property in the components changes, the template is updated to reflect the new changes.

This binding is one-way in the sense that, the Model’s property can only be updated from the Model side and the View is updated or the Model’s variables are kept up to date from the View. The data flow is in one direction either from Model-to-View or View-to-Model.

For example, we have this component:

@Component({

template: `

<div>

<h2>

{{message}}

</h2>

</div>

`

})

export class AppComponent {

message = "My Message"

}

The Model (AppComponent) have a property message with the value My Message . We can reference this property by appending the property name to . reference operator after the instance name.

const appC = new AppComponent();

log(appC.message) // logs: `My Message`

The markup of the component needs to display the value of the message property in the {{message}} . In essence, we use the double braces {{}} to tell Angular that we want to render a Model data in the View where the {{}} is located.

So now in AppComponent when the template is rendered, the {{message}} is replaced with 'My Message' .

<div>

<h2>

{{message}}

</h2>

</div> |

v <div>

<h2>

My Message

</h2>

</div>

If we change the message property in the component like this

@Component({

template: `

<div>

<h2>

{{message}}

</h2>

</div>

`

})

export class AppComponent {

message = "My Message"

cosntructor() {

setInterval(()=>this.message = Date.now(), 1000)

}

}

After every 1ms interval, the message property is updated to the current time. This causes the template in the DOM to update to reflect the new message value.

Sometimes the template expression gets more complicated. Angular attempts to evaluate that expression (which can contain math, property names, method calls, and more) and converts the evaluation into a string. Then it replaces the contents and the curly braces with the result.

The template expression might be a JavaScript expression, but usually, it is the component’s property.

Template expression can be:

method calls {{methodCall()}}

JS expression {{}}

Math {{2 * 8 / 67}}

Conditional expression

String concatenation {{‘string’ + ‘concatenation’}}

It is left for the Angular compiler to detect which one it is in the list above and generate compiled code accordingly.

Property Binding []

This a one-way binding of a Model’s data to the binding target.

The binding target can be element properties, components properties or directives directives properties.

In between the square brackets [] is the name of the Model's property to be bound to the element.

Element Binding

@Component({

template: `

<div>

<img [src]="imageURL" />

</div>

`

})

export class AppComponent {

imageURL = "./images/k.png"

constructor() {

setInterval(()=>this.imageURL = './images/p.png', 1000)

}

}

The img element's src property is bound to the imageURL property in the AppComponent class. The src property in the img element is used to set the image that will be displayed on the element.

We can get the HTMLImgElement instance and refer to the src property to set the image on the img element.

const imgElement = document.getElementById('img_1');

imgElement.src = './images/p.png';

imgElement.src = './images/k.png';

If the imageURL property changes in the AppComponent class the src property in the img element will be changed. When rendered it will be like this:

<div>

<img [src]="imageURL" />

</div> |

v <div>

<img src="./images/p.png" />

</div>

After the imageURL changes after 1ms interval by setInterval(...) call. This will be rendered.

<div>

<img [src]="imageURL" />

</div> |

v <div>

<img src="./images/k.png" />

</div>

So when we use [] on element properties we are telling Angular that the property should take the value of the Model's property passed to it.

Component Binding

@Component({

template: `

<child [data]="dataSource"></child>

`

})

export class Parent {

dataSource = 'My Source'

constructor() {

setInterval(()=> this.dataSource = "My S" + Date.now(),1000)

}

} @Component({

selector: 'child',

template: `

<h2>{{data}}</h2>

`

})

export class Child {

@Input data

}

The Child component is rendered on the Parent markup. The Parent uses [] to bind data property of Child to its dataSource property. When the dataSource changes the data property in the child is updated to reflect the new changes. In Angular components use the @Input decorator to tell which property is open to the outside world.

So in our case, child appended @Input to data property because it will be bound to by the parent component.

Simplifying the process of component binding we write a simple implementation in JS:

Event Binding ()

This while we have been dealing with passing data from parent-to-child. Now we will see how we can pass data upwards from child to parent.

In the DOM, elements can raise events and we bind each event with an event handler, a function that is run when the event is emitted.

<button onclick="runHandler">Click Me</button>

<script>

function runHandler($event) {

console.log(`'Click Me' button clicked`)

}

</script>

We have a button Click Me , and an event onclick attached. When the button is clicked on the function runHandler is run.

Likewise, in Angular we can attach events to our elements in our component’s template, this is done using the brackets () .

@Component({

template: `

<div>

<button (click)="clickHandler()">Click Me</button>

<input (change)="changeHandler()" placeholder="Enter your name" />

</div>

`

})

export class AppComponent {

clickHandler() {

// ...

}

changeHandler() {

// ...

}

}

Above, the Click Me button is attached a click event and an event handler clickHandler . When the button is clicked the method clickHandler in the AppComponent is run.

Likewise, the input has a change event attached to it. The change is triggered when the value of the input is changed or new value is typed in the textbox. When the change event is fired the changeHandler method is run.

In Angular the format of event binding is:

(event name) = "event handler expression"

The event name between () must be in the list of HTML DOM events.

We can attach and emit customs events other than those in the HTML DOM Standard in Angular. We can create our own event, listen to it and run the corresponding function handler.

Angular components can create and emit custom events.

<child (deposit)="depositMoulah()"></child>

The element child is an Angular component not an HTML element. We attached an event to it using the () and passed deposit to it. deposit is no in any way an HTML event. This is a custom event created by Angular.

Angular uses the concept of EventEmitter to create and emit events. The binding component declares an event variable with the Output decorator and sets it equal to a new EventEmitter. This instance of EventEmitter is used to emit events.

The parent component creates a function to receive the message and set it equal to the child property.

@Component({

template: `

<child (deposit)="depositMoulah"></child>

`

})

export class Parent {

depositMoulah() {

// ...

}

} @Component({

selector: 'child',

template: `

<h2>Child Component</h2>

`

})

export class Child {

@Output deposit = new EventEmitter()

constructor() {

setInterval(()=>this.deposit.emit(),1000)

}

}

When the Child component, calls the .emit() method in the EventEmitter class, the deposutMoulah method in the Parent component is called. The Output decorator tells Angular that the property name is to be used to call the binding event on the Child when the component emits an event from the Parent component.

We can pass data from the Child component to the Parent using this () concept.

@Component({

template: `

Data recieved: {{data}}

<child (deposit)="depositMoulah"></child>

`

})

export class Parent {

data = null;

depositMoulah($event) {

this.data = $event.value

// ...

}

} @Component({

selector: 'child',

template: `

<h2>Child Component</h2>

`

})

export class Child {

@Output deposit = new EventEmitter()

constructor() {

setInterval(()=>this.deposit.emit('data from Child' + Date.now()),1000)

}

}

With the .emit() method in the EventEmitter we can pass in the data/message we want to comm to the parent. Then the parent will get the message in the $event object.

Banana in the Box [()]

This is a term coined from merging property binding with event binding: [()] to gain the two-way binding power.

[property binding]

-------> [(two-way binding)]

(event binding)

With this communication is two-way from the Model to the View and View to the Model.

You can change the Model data from the View and also from the Model and both will reflect the changes.

With both property binding and event binding, we can achieve two-way binding. Let’s elaborate with an example:

@Component({

template: `

Data recieved: {{parentMessage}}

<child (messageChange)="sendMessage" [message]="parentMessage"="amount"></child>

`

})

export class Parent {

parentMessage = null;

constructor() {

setInterval(()=>{

this.parentMessage = 'data from Child' + Date.now()

}, 1000)

}

sendMessage($event) {

this.parentMessage = $event.value

// ...

}

} @Component({

selector: 'child',

template: `

<h2>Child Component</h2>

<h3>{{message}}</h3>

`

})

export class Child {

@Output messageChange = new EventEmitter()

@Input message: any

constructor() {

setInterval(() => {

this.message = 'data from Child' + Date.now()

this.messageChange.emit(this.message)

}, 1000)

}

}

See what is happening, the Parent and Child components can set and change the message property in the Child component. In the Parent component, the message property is bound to the parentProperty, so when it changes the new value is reflected in the Child component. Then, the Child emits a messageChange event, the Parent component vent binds it that it updates its value with the value of the message property sent by the Child component. You see with this the communication is two-way the message property in the Child can be updated from both the Parent component and the Child component.

Instead of having two-way binding by writing so many template expressions, we can simplify it by using one expression. The Angular compiler was made to recognize two-way binding [()] .

The magic is to append Change to the Output with the name being the same as the Input.

So this:

<child (messageChange)="sendMessage" [message]="parentMessage"="amount"></child>

could be written like this:

<child [(message)]="message"></child>

The trick here is that if the property binding name is event , then the event binding should be eventChange . The event name should be the same as the property binding but suffixed with Change. This is to let Angular detect that you are performing a two-way operation.

Now, we can rewrite our above code:

@Component({

template: `

Data recieved: {{parentMessage}}

<child [(message)]="parentMessage"></child>

`

})

export class Parent {

parentMessage = null;

constructor() {

setInterval(()=>{

this.parentMessage = 'data from Child' + Date.now()

}, 1000)

}

} @Component({

selector: 'child',

template: `

<h2>Child Component</h2>

<h3>{{message}}</h3>

`

})

export class Child {

@Output messageChange = new EventEmitter()

@Input message: any

constructor() {

setInterval(() => {

this.message = 'data from Child' + Date.now()

this.messageChange.emit(this.message)

}, 1000)

}

}

You see, its simpler and neat.

The most popular Directive used in this way is the ngModel: [(ngModel)] . Looking into the sources, we will see it does the same as above using the Change suffix in its event binding name.

@Directive({

selector: '[ngModel]:not([formControlName]):not([formControl])',

providers: [formControlBinding],

exportAs: 'ngModel'

})

export class NgModel extends NgControl implements OnChanges,

OnDestroy {

@Input('ngModel') model: any; @Output('ngModelChange') update = new EventEmitter(); }

You see it, the property binding name is ngModel and the event binding name is ngModelChange , Change is suffixed to it. So now we can use ngModel enclosed inside Banana-in-the-Box.

@Component({

template:`

{{propName}}

<input [(ngModel)]="propName" />

`

})

export class App {

propName = ''

constructor() {

setInterval(()=> this.propName = Date.now(), 1000)

}

}

Typing in the input changes the propName property in the App component and the setInterval call updates the propName which reflects in the ngModel.

Conclusion

In this post, we looked into data binding in Angular. We saw how one-way bindings by template expression {{}} and property binding [] works. Later on, we saw just two way-binding works using the banana-in-the-box concept [()] .

Data binding in Angular is not overly complex, it is easy to understand and with the understanding strengthens your confidence when using data binding in your next Angular project.

If you have any question, feel free to comment below and ask me anything- I’d love to talk 🍻 Thanks!!!