Event Binding in Angular
In our journey of learning Angular we have covered quite a lot of things up until now. We also touched on some necessary concepts for having our work done for the time being. To change views and data dynamically we learned interpolation, property binding, attribute binding, style binding and class binding. In this article we are going to learn about event binding.
The syntax of event binding is very simple. In the opening tag of an HTML element you will have to use the following syntax:
(event_name)="aMethodCall()"
We can write unnecessarily complex code in place of the method call, but that is not a concern of this article. Let's stick to the rules for now.
Before we proceed I want to discuss the data and event flow direction. Did you notice the flow of data in all the previous articles? Did you notice who provided data and who consumed it in interpolation and property binding (everything we used with the syntax of property binding)? In interpolation and property binding, data flows from the component (the component object created from the component class) to the target (the template or the view)—not the other way around. So, the flow of the data is unidirectional. In the case of event binding the opposite happens. In event binding events are generated in the view (in the DOM elements) and flows to the component. It is unidirectional also in this case.
Now, let's prepare our HTML template to do what we want to do next. We want to put a delete button beside our social links so that when we click that button the link associated with that link object is removed from the DOM and from the array. The event name for click is click in Angular HTML template. I am removing all the class and style property binding from the HTML template and associated code from the TypeScript file.
<h1>My profile</h1>
<b> Hello World </b> <br/>
My name is Md. {{ name }} <br/>
I am a {{ profession }}. <br/>
Do not forget to visit me at: {{ website }} <br/>
My Social Links:
<ol>
<li *ngFor="let link_obj of social_links; let idx = index">
<a *ngIf="link_obj.is_active; else elseTemplate" [href]="link_obj.link"> {{ link_obj.title }} </a>
<ng-template #elseTemplate>
<s> This link is not active </s>
</ng-template>
| <button (click)="removeLink(idx)"> Remove This Link</button>
</li>
</ol>
Look at the button code: <button (click)="removeLink(idx)"> Remove This Link</button>. It binds the click event to a function called removeLink with idx as the parameter. We will define this method in our template class. But what the heck is that idx and where does it come from? idx is the index of the of link object in our link array in the component. Look at the ngFor portion and you will see that I have modified it: \ngFor="let link_obj of social_links; let idx = index". Look at the newly added portion: let idx = index". index is automatically available in ngFor* and we want to use that later and thus we need to save that inside a variable so that it does not get lost. That's how it all came into the way.
Now we need to create the method for removing an element from that index so that our view gets updated.
class AppComponent {
name = "Md. Sabuj Sarker";
profession = "Software Engineer";
website = "http://sabuj.me";
social_links: ISocialLink[] = [
{ title: "Facebook", link: "https://facebook.com/SabujXiP", is_active: true },
{ title: "Twitter", link: "https://twitter.com/SabujXi", is_active: false },
{ title: "Github", link: "https://github.com/SabujXi", is_active: true }
];
removeLink(idx){
this.social_links.splice(idx, 1);
}
constructor(){
}
}
We are using splice method with the first positioning argument as the index and the second positional argument to indicate how many elements we want to remove—we want to remove only one element and thus I have put 1 there. Now go to your browser to see the changes. Keep clicking on the remove buttons and you will see that the associated links are being removed and the list is getting reorder with proper numbering.
As the event name you can use any of the DOM element events, for example, click, dblclick, mousedown, mouseenter, mouseup, keydown, keyup, blur, change, focus, select, etc.
Let's create an input text field and display that text in another portion of the template in real time. Add the following code below the preexisting HTML template.
Your Quote: <br/>
<input type="text" value="" (keyup)="inputChanged($event)"> <br/>
You have written: {{ current_quote }}
$event is a special variable that contains the native event—in this case it will be a keyup event. We are passing it to the method so that we can get the current value in the input field. current_quote will hold the currently written quote in the component.
Add inputChanged and current_quote inside our component class like below:
current_quote = "";
inputChanged(evt){
if (evt.target.value){
this.current_quote = evt.target.value;
}
}
Go to the browser, start typing your own quote in the text box and you will see that the same text is being populated below it.
Now we want to place another button below the input called save so that when we click the save button the quote is added to an array of quotes and a list is also shown with saved quotes. So, our HTML should look like below:
<h1>My profile</h1>
<b> Hello World </b> <br/>
My name is Md. {{ name }} <br/>
I am a {{ profession }}. <br/>
Do not forget to visit me at: {{ website }} <br/>
My Social Links:
<ol>
<li *ngFor="let link_obj of social_links; let idx = index">
<a *ngIf="link_obj.is_active; else elseTemplate" [href]="link_obj.link"> {{ link_obj.title }} </a>
<ng-template #elseTemplate>
<s> This link is not active </s>
</ng-template>
| <button (click)="removeLink(idx)"> Remove This Link</button>
</li>
</ol>
Your Quote: <br/>
<input type="text" value="" (keyup)="inputChanged($event)" #inputElem> <br/>
<button type="button" (click)="saveQuote(inputElem)">save quote</button> <br/> <br/>
You have written: {{ current_quote }}
<ol>
<li *ngFor="let quote of quotes">{{ quote }}</li>
</ol>
Now we need to code our component class accordingly:
class AppComponent {
name = "Md. Sabuj Sarker";
profession = "Software Engineer";
website = "http://sabuj.me";
social_links: ISocialLink[] = [
{ title: "Facebook", link: "https://facebook.com/SabujXiP", is_active: true },
{ title: "Twitter", link: "https://twitter.com/SabujXi", is_active: false },
{ title: "Github", link: "https://github.com/SabujXi", is_active: true }
];
current_quote = "";
quotes = [];
removeLink(idx){
this.social_links.splice(idx, 1);
}
saveQuote(){
if (this.current_quote){
this.quotes.push(this.current_quote);
}
}
inputChanged(evt){
this.current_quote = evt.target.value;
}
constructor(){
}
}
Now go the browser again. Type your quote, and see the live update below. Keep changing the quote and click the save button, you will see a list getting populated with quotes below.
Conclusion
The event bindings we saw in this article are DOM events. We can create custom events too. We can create and fire events from components that we will see in cross component communication in future lesson. Keep practicing and keep coding with Angular.
About the Author
My name is Md. Sabuj Sarker. I am a Software Engineer, Trainer and Writer. I have over 10 years of experience in software development, web design and development, training, writing and some other cool stuff including few years of experience in mobile application development. I am also an open source contributor. Visit my github repository with username SabujXi.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment