Angular is a popular javascript framework that offers many ways for data binding one of which is two-way data binding. It enables live communication between the user interface and underlying data. Modified data in the view is automatically reflected in the source and vice versa. While two-way binding simplifies development in many scenarios, sometimes even some alternate approaches may take an edge over it.
This exploration not only aims to some alternative approaches to two-way binding but also helps to understand why and when these methods are useful. As we explore these approaches we see the power of angular which allows the developer to choose a suitable binding mechanism for their application. Using alternative approaches of two-way data binding in angular will help create a more robust, maintainable, scalable, and efficient application.
Data binding is essential for a smooth transition of data from view to model and model to view.
Angular provides 3 ways to exchange data between view and model.
source to view
view to source
source to view to source
This source to view data binding, also called one-way data binding includes string interpolation and property binding. In this binding, we are passing the values to view from the source.
What is interpolation?
Angular string interpolation is the most commonly used technique for displaying data to the user. It gets data from the source and embeds it into view. By default, string interpolation uses double curly braces "{{}}" as delimiters.
We can change the default syntax of string interpolation as the following code.
/* app.component.ts */
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
interpolation: [``, `]`]
})
export class AppComponent {
title:any = "test title";
}
<!-- app.component.html -->
<!-- html file -->
<h1>
This is a app title:- [ title ]
</h1>
What is Property binding?
Property binding allows us to bind data from source to HTML elements or directives. Property binding is used to make toggle button features, set paths programmatically, and share values between components. It also helps us to set an HTML property's value dynamically.
An example of property binding is shown below:
/* app.component.ts */
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
title = "data binding";
}
<!-- app.component.html -->
<input type="text" style="margin: 20px 10px 0 10px; color: gray;" [value]="title">
The output for the above code snippet will be displayed as follows :
Syntax of property binding "[]" shows that the right side value is a dynamic value otherwise it is considered as a string or static value.
<!-- binds dynamic value from .ts file, suppose title contains "Angular" it binds --> <!-- "Angular" with this input. -->
<input type="text" [value]="title">
// It will consider "title" as string and binds it
<input type="text" value="title">
This data binding is also known as event binding and in this technique, data flows from view to source.
There are so many predefined events in angular but the most commonly used are click, scroll, change, and keyup. These are used to trigger events from view.
An example of event binding is shown below :
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-root',
template: `<button (click)="getData()">getData</button>`,
styleUrl: './about.component.scss'
})
export class AppComponent {
getData(){
console.log("Event binding works");
}
}
In the above example, we bind the click event with the button. Whenever the user clicks on the button then the click event is triggered and the "getData()" function of the source will be called.
Two-way data binding gives you a way to share data between view to source and vice versa simultaneously. When we bind data using two-way data binding the view and source are in sync and updated data accordingly.
Two-way data binding uses the "ngModel" directive to bind the data and we need to import the Forms Module to use it otherwise it will throw an error.
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-root',
template: `<input type="text" [(ngModel)]="title"> <br>
<p>Title is {{title}}</p>
`,
styleUrl: './about.component.scss'
})
export class AppComponent {
title = "New Blog";
}
In the above code snippet we have bound the title with the input tag with the help of two-way data binding. Initially, it will display "New Blog", whenever we change the input box value it changes the current value and is automatically reflected in the view.
Two-way data binding is a combination of property binding "[]" and event binding "()" and its syntax is called banana in a box syntax [( )].
Let's see how two-way data binding internally works:
<input [ngModel]="user" (ngModelChange)="user = $event">
<p>Hello {{user}}!</p>
ngModel directive comes with property and event binding. The short form of this syntax is [(ngModel)]="user".
We can create our custom two-way data binding without the help of ngModel directive as shown below:
<input [value]="user" (input)="user = $event.target.value">
<p>Hello {{user}}!</p>
Here we have set a variable called user in our source and bind it with the help of property binding with the input field and attach an input event that is triggered when the value changes inside that input and the updated value is set to user.
We can avoid two-way data binding using one-way binding and event emitters or event binding. Please refer below code to understand how it works.
<!-- parent component -->
<!-- parent.component.html -->
<app-child-component (userChanged)="dataChange($event)"></app-child-component>
Welcome {{user}}!
//parent.component.ts
user:string;
dataChange(value:string){
this.user = value;
}
<!-- child components -->
<!-- child.component.html -->
<input type="text" [value]="title" (keyup)="onUserChange($event.target.value)">
<!-- child.component.ts -->
@Output() userChanged: EventEmitter<string> = new EventEmitter<string>();
onUserChange(newValue: string) {
this.userChanged.emit(newValue);
}
In the above example, we have created two components parent and child. We have created a parent-child relationship for data sharing through the output decorator. Here I have created an onUserChange method that triggers the userChanged event whenever a keyup event occurs on the input field and the new value is sent to the parent component class and assigned to the user variable which simply renders "hello" with user value without using two-way data binding.
ngModel directive is commonly used for two-way data binding in angular. In the below example, we see how we can use the ngModel directive to gain more control over data flow using the "noModelChange" event.
<!-- app.component.html <input type="text" [ngModel]="user" (ngModelChange)="changeUser($event)"> Hello {{user}} -->
<!-- app.component.ts -->
user:string;
changeUser(value:string){
this.user = value;
}
In the above example, we have created a "ngModelChange" event which is responsible for updating the value inside the user and binding the user with the "ngModel" directive to the input field.
Angular provides reactive forms and template-driven forms to deal with forms. We can use reactive forms as an alternate approach to two-way data binding in angular. Please refer below code:
<!-- app.component.html -->
<form [formGroup]="form" (ngSubmit)="submit()">
<input type="text" name="name" ngModel formControlName="name">
<button type="submit">Submit</button>
</form>
Hello {{form.controls["name"].value}}
<!-- app.component.ts -->
form!: FormGroup;
ngOnInit(){
this.form = new FormGroup({
name: new FormControl('')
});
}
submit(){
/* submit logic here... */
console.log(this.form.value)
}
In the above example, we have created a reactive form which is bound inside app.component.html with form using formGroup directive and created a button to submit form. Inside the view, we display the name of the user without using angular two-way data binding.
Subjects are part of rxjs (Reactive extension for javascript). Subjects are multicast so that each observer gets the latest value. Let's explore how to use subjects as an alternative two-way data binding.
<!-- app.component.html -->
<input type="text" (keyup)="onValueChange($event)">
Hello {{user | async}}
<!-- app.component.ts -->
user = new Subject<string>();
onValueChange(event:any){
this.user.next(event.target.value);
}
In the above example, he have created a user subject and updated the value on each "keyup", after every update in the user subject we get the latest value through subscription in the view. The Async pipe is simply used for subscribing the user subject otherwise we can create a subscription through the .ts file.
Two-way data binding is known for its banana-in-a-box syntax but some people make mistakes while writing it like they forget the parentheses or write the wrong word instead of "ngModel". Please refer below code snippet for correct syntax:
/* Incorrect syntax */
<input type="email" ngModel="email">
/* Correct syntax */
<input type="email" name="email" [(ngModel)]="email">
/* Incorrect syntax */
<input type="email" ngModel="email">
/* Correct syntax */
<input type="email" name="email" [(ngModel)]="email">
Some people are forgot to write name attribute it will cause undesired results, so that it is highly recommended to use name attribute for proper functioning.
/* Incorrect syntax */
<input type="email" [(ngModel)]="email">
/* Correct syntax */
<input type="email" name="email" [(ngModel)]="email">
While using "ngModel" it simplifies the data transfer but it's over use can reduce the performance of your application, because two way data binding trigger change detection multiple times for value update which cause performance issues.
Both one way binding and two way data binding have their pros and cons let's discuss which one is better in which scenario:
Performance: Performance of one way binding is better than two way data binding because data flow in one way binding is uni directional so it triggers less change detection cycles which ultimately improves the performance.
Memory usage: here also one way data binding takes lead because two way data binding need to track the state of both model and view which needs more memory as compared to one way data binding.
Readability: In case of readability two way data binding is more readable as compared to one way data binding due to its super easy syntax "[(ngModel)]" which makes it more readable as compared to one way data binding.
Modularity and re-usability: here also one way binding takes advantage because two way data binding is tightly coupled and it's re-usability is very less but in case of one way binding code is more modular and reusable. We can reuse the component in different parts of our application.
Complexity: two way binding is more complex and high chances of bugs introduction in your app. If we are not careful about it's use it may give us undesirable results and may be it affects other values also.
In conclusion, Angular provides mainly two types of data flow uni-directional and bi-directional. String interpolation, property binding and event binding are the uni directional data flow and two way data binding is the bi directional data flow. Two way data binding comes with it's simple syntax and bi directional data flow from view to source and vice versa so that the changes occurred in one will be reflected on other but we should cautious about performance issues and memory usage.
Several alternative approaches we are explored including one way binding with event binding, ng model directive with "ngModelChange" event, reactive forms and use of subjects which are the parts of rxjs. These are the some alternatives of two way data binding which provides performance boost, modularity, code re-usability and flexibility.
Common mistakes and their corrections we are discussed importance of correct syntax and name attribute to avoid undesired results, overuse of "ngModel" can cause performance issues so we should be aware about that.
In the comparison between one way data binding vs two way data binding, one way data binding gets a edge because of it's performance, modularity, re-usability, memory usage and complexity. While two way data binding offers readability benefits with it's easy syntax.
In summary choice between one way data binding or two data binding depends on project's requirement, but performance, modularity and re-usability of one way data binding is better.
This website uses cookies to analyze website traffic and optimize your website experience. By continuing, you agree to our use of cookies as described in our Privacy Policy.