This article continues the discussion on data binding. The last article discussed the importance of data binding in front-end frameworks and it explained the interpolation and property binding in Angular with examples.
This article will cover event binding and two-way binding in Angular.
Event Binding in Angular
A user expects a UI to respond to her/his actions on the page. Every such action would trigger an event on the page and the page has to respond by listening to these events.
The event binding system provides us the way to attach a method defined in a component with an event. Like property binding, event binding is built on top of the events defined in the DOM objects.
With Angular, there are two ways to handle an event on an HTML element. The following snippet shows both the ways for handling a click event on a button:
<button class='btn' (click)='submit()'>Submit</button>
<button class='btn' on-click='submit()'>Submit</button>
Here, the method submit has to be defined in the component class. Any DOM event can be either prefixed with on- or can be enclosed inside parentheses to bind it with a method in the component class.
Functionally, there is no difference in the two ways of handling events, you can choose the one you like, and use it. As the process of handling events doesn’t involve any abstractions which has to be written for any event on the page, this model is extensible. Any new events added to a DOM element can be bound to functions in the component using this syntax without writing any piece of new code.
Events can be used to run a piece of logic based on the action taken by the user. It may include changing values of a few fields in the component, posting data to a REST API, moving to a different page or anything else. As the events directly correspond to the browser’s events, every event adds an entry to the event loop.
All of this means Angular’s change detection cycle runs whenever an event is triggered. So, any values modified by the event handler will be detected by the change detection system and the changes are applied on the page.
The following component shows an example of event binding:
@Component({
selector: 'app-demo',
template: `<div>{{submitText}}</div>
<button class="btn" (click)='submit()'>Submit</button>`
})
export class DemoComponent {
public submitText: string = 'Not submitted yet.';
submit(){
this.submitText = 'Submitted successfully!';
}
}
The above component has a div element and a button. The div element has an interpolation applied, text of the interpolated expression is modified in the click event handler of the button. You will see that the text inside the expression is modified after clicking the button.
If an event has to perform a single action like changing a simple value, it can be done in the HTML instead of writing a separate method. The following snippet shows an example:
<button class='btn' (click)='color="green"'>Submit</button>
But if the event involves a few more lines of logic, it should be kept outside HTML to separate the concerns. This way, the code in the event handler can be unit tested as well.
The event handling method gets access to the event object, which is same as the object passed into any DOM event handler. This object gives us access to the information about the event. The following snippet shows how to pass the event object from HTML to the event handling object:
<button class='btn' (click)='submit($event)'>Submit</button>
The $event object is same as the object that the browser sends when an event is triggered on an HTML element. We can get details of the event like source of the event, target element, type of the event, co-ordinates on the page and screen where the event triggered, as well as many other details.
The following snippet shows a component handling two events on a button:
@Component({
selector: 'app-demo',
template: `<div>{{submitText}}</div>
<button class="btn" (click)='submit($event)' (mousemove)="mouseMove($event)">Submit</button>
<div>{{x}} {{y}}</div>`
})
export class DemoComponent {
public submitText: string = 'Not submitted yet.';
public x: number;
public y: number;
submit($event: Event){
this.submitText = 'Submitted successfully!';
console.log($event);
}
mouseMove($event: MouseEvent) {
this.x = $event.x;
this.y = $event.y;
}
}
The component in the above snippet has a button, on which the click and mouse move events are handled using methods in the component. The click event changes the text displayed in the div element and the mouse move event updates values of the co-ordinates displayed on the screen.
Figure 1 – Event binding
You can explore this example in this plunk: http://plnkr.co/edit/y7aSXxqTJZ5OFTC58tqV?p=preview
Two-way Binding in Angular
The feature two-way binding in Angular is derived from the property and event bindings. The property and event bindings are directed one way with the former receiving data into view from the component object and the later sending data from the view to the component. The two-way binding is a combination of these two bindings; it gets the data from the component object to the view and sets the data from view to the component object.
The following snippet shows an example of a directive, ngModel to show how two-way binding can be used:
Name: <input type="text" [(ngModel)]="name" />
<div>{{name}}</div>
Here, the field name is two-way bound on the input box. When it is rendered on a page, it shows the existing value of the field and when the value is modified on the screen, it updates the value in the field. The change in the value of the field is immediately reflected in the interpolation in the div element next to the input control.
To use the ngModel directive, the FormsModule has to be added to the application’s module. The following snippet shows the application module using the FormsModule:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; // Importing forms module to this file
import { AppComponent } from './app.component';
import { DemoComponent } from './demo.component';
@NgModule({
imports: [
BrowserModule,
FormsModule // Importing forms module to application module
],
declarations: [
AppComponent,
DemoComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
The following component uses the ngModel directive:
@Component({
selector: 'app-demo',
template: `
Name: <input type='text' [(ngModel)]='name' />
<div>Name is: {{name}}</div>
`
})
export class DemoComponent {
public name: string = "Ravi";
}
The textbox is bound to the field name in the template. When you type something in the textbox, you will see that the content in the div changes automatically. Figure 2 shows a running instance of this component:
Figure 2 – Two-way binding
Conclusion
Angular provides an easy way to handle events on the DOM elements. The 2-way binding technique really helps in keeping the data in the model and the input control in sync. Hope this article got you started with these features. These features will be used extensively in the upcoming articles.
This article was technically reviewed by Keerti Kotaru.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Rabi Kiran (a.k.a. Ravi Kiran) is a developer working on Microsoft Technologies at Hyderabad. These days, he is spending his time on JavaScript frameworks like AngularJS, latest updates to JavaScript in ES6 and ES7, Web Components, Node.js and also on several Microsoft technologies including ASP.NET 5, SignalR and C#. He is an active
blogger, an author at
SitePoint and at
DotNetCurry. He is rewarded with Microsoft MVP (Visual Studio and Dev Tools) and DZone MVB awards for his contribution to the community