Angular bindings are a super-powerful mechanism built into the framework. Unfortunately, they can be difficult to remember. This blog post by Alyssa Nicoll will help.
Angular provides a powerful mechanism for a wide range of bindings. You don’t have to be new to forget which binding is which. Sometimes, when reaching for the right binding, I mess up or forget the syntax. I thought an article might help clarify how and when to apply bindings in your Angular applications, for those memory moments we all sometimes have.
Below is a handy-dandy chart for quick reference (linked to each section):
Binding | Example |
---|---|
Property Binding | <input [placeholder]="placeholderValue" /> |
String Interpolation | <input placeholder="{{placeholderValue}}" /> |
Attribute Binding | <td [attr.colspan]="clspn"> |
Style Binding | <input [style.borderStyle]="'dashed'" /> |
Class Binding | <input [class.active]="true" /> |
Event Binding | <input (keyup.enter)="onEnter()" /> |
Two-way Binding | <input [(ngModel)]="value" /> |
It includes all of the types of Angular Bindings along with a line of markup showing how that binding can be used. We'll cover all the bindings in more detail in the sections below, except for attribute binding, which I found to be quite uncommon.
In Angular, the simplest binding is property binding. It uses `[ ]` brackets to get the job done. It is a one-way binding from the component to the template.
<input [placeholder]="placeholderValue" />
You can also use string interpolation to get the same property binding done:
<input placeholder="{{placeholderValue}}" />
String interpolation is best suited for text between opening and closing elements:
<h2>{{amazingTitle}}</h2>
This same approach can be done through property binding but it's less intuitive. In the example above, we can achieve the same result through the textContent
attribute:
<h2 [textContent]="amazingTitle"></h2>
Ultimately, it comes down to personal preference. Buttons in Kendo UI take advantage of different property binding types in order to give you the ability to customize the look of our buttons. For example, you can set [icon]
to any number of icons (found here). You can also set the [look]
of the button to outline
, flat
, or default
! You can read more about the awesome customizable Kendo UI button here.
<button kendoButton [icon]="'folder'" [look]="'outline'">{{btnValue}}</button>
Here, we are using string interpolation to bind the value of the button. At the same time, we're using property bindings for its icon
and look
. It's important to mention that both binding types are one-way bindings; from the component to the template. You'll have to use discretion for which type of binding you use. Again, it comes down to personal preference.
Another type of property binding is style binding. We can add styles inline with logic! If we’d like to apply some inline styles to this button we can do so inside the square brackets:
<button kendoButton ... [style.backgroundColor]="'rebeccaPurple'"></button>
In the example above, we've changed the background color to rebeccaPurple
, but any CSS-acceptable color value (HEX, RGB, etc) will work. Check W3Schools for a full list of DOM style properties you can bind to.
Let's now look at the same example but with some logic:
<button kendoButton ... [style.backgroundColor]="isActive ? 'rebeccaPurple' : 'white'"></button>
Here, we are binding the background color to rebeccaPurple
only if the isActive
variable is true
. Otherwise, the background color is set to white
.
So style binding is just property binding to style [style.PROPERTY]
followed by the property you'd like to modify.
The last version of property binding is class binding. This is very similar to style binding; instead of muddying up our template with inline styles, you add an active
class to an element and handle the styling in an associated stylesheet. In the following example, we are applying the active
class based on the state of isActive
in the component:
<button kendoButton ... [class.active]="isActive"></button>
/* styles.css */
.k-button.active {
background-color: rebeccaPurple;
color: white;
}
The .k-button
class is used for specificity and would not be needed in all cases.
Our button is pretty snazzy, however we need to actually be setting/unsetting the isActive
variable. We can use event binding to capture a variety of user-initiated events and initiate logic in our component class. Angular supports many kinds of events. If we'd like to catch the click event on our button and bind it to a method, we can do so, using parentheses:
(click)="toggleActive()"
Here, we are binding the toggleActive
method to be called on button click
. The toggleActive
method is just setting the active
variable to !active
. Then we are using the class binding to give our button an active
class. The button will be rebeccaPurple when active and grey when not. We also set these changes to happen on hover when active: .k-button.active:hover
.
/* styles.css */
.k-button.active, .k-button.active:hover {
background-color: rebeccaPurple;
color: white;
}
// app.component.ts
<button kendoButton
[icon]="'folder'"
[look]="'outline'"
[class.active]="isActive"
(click)="toggleActive()">
{{btnValue}}
</button>
So far, we've examined the various ways to establish unidirectional or one-way bindings. Another type of binding is a bidirectional or two-way binding. Two-way bindings are used when a developer wishes to propagate changes made to an underlying value or event between a component and its template.
In Angular, we can use ngModel
to create that two-way data binding. Let's use the same example we built earlier with Kendo UI. First, we have to import the FormsModule
in order to have access to ngModule
:
Next, we need to include Kendo UI inputs for this example:
Now, we are ready to establish a two-way binding:
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<input kendoTextBox [value]="email" (keyup.enter)="onEnter()" />`
})
export class AppComponent {
email = "bob@gmail.com";
// ...
onEnter() {
alert(this.email);
}
}
Here, we are using the property binding to bind the value of this kendoTextBox
to email. The keyup.enter
event is bound to the onEnter()
method that displays the email entered by the user. Unfortunately, when we change the <input> element and hit enter, the alert is not updated. What is going on?
In this example, the property binding, which as you recall, is a one-way binding (only FROM the component TO the template). We need to use a two-way binding! This is where the formsModule
comes in. We'll use the ngModel
for two-way binding, which comes from the formsModule
:
<input kendoTextBox [(ngModel)]="email" (keyup.enter)="onEnter()" />
Now, instead of a one-way binding, we are two-way binding with [(ngModel)]
. For this we are going to need to use both the square brackets and parentheses [()]
. The email value now changes in the displayed alert. 🙂 It works! It works!
To recap, one-way bindings use the []
square brackets for property, style, and class bindings. For event bindings, we need to use parentheses ()
and for two-way binding, we use both [()]
square brackets and parentheses!
Binding | Example |
---|---|
Property Binding | <input [placeholder]="placeholderValue" /> |
String Interpolation | <input placeholder="{{placeholderValue}}" /> |
Attribute Binding | <td [attr.colspan]="clspn"> |
Style Binding | <input [style.borderStyle]="'dashed'" /> |
Class Binding | <input [class.active]="" /> |
Event Binding | <input (keyup.enter)="onEnter()" /> |
Two-way Binding | <input [(ngModel)]="value" /> |
I hope you've enjoyed this binding party and never get them mixed up again! Here are some extra links to docs about the components used above. Happy coding!
Alyssa is an Angular Developer Advocate & GDE. Her two degrees (Web Design & Development and Psychology) feed her speaking career. She has spoken at over 30 conferences internationally, specializing in motivational soft talks, enjoys gaming on Xbox and scuba diving in her spare time. Her DM is always open, come talk sometime.