Two of the most fundamental parts of any application are Data and UI. It is crucial to find an efficient way to wire them up together.
In case of rich UI applications, the data can arrive in several chunks and the UI has to be kept updated with the latest data.
Say, you are building a hospital management application and the application has a dashboard for doctors. Let’s assume the dashboard has ten widgets showing information like number of patients consulted in last five days, recent surgeries and other relevant information. The developers working on these widgets would have a hard time in capturing the return value of each of the requests, and put the data in these widgets.
If the dashboard has to be updated in real-time, the code will have to rebuild the widget whenever it receives new data. jQuery developers are quite familiar with the pain involved in updating the UI by hand whenever a new piece of data arrives from the server. It involves iterating over the data received, building each small piece of the HTML programmatically and manually replacing it in the HTML of the page. This task has to be repeated for any small update to the data, thus making the process quite inefficient.
In the current world of front-end development, JavaScript frameworks like Angular do a lot of work for us. We expect the heavy-lifting work of synchronizing the data and UI to be taken care by these frameworks. The technique of synchronizing the data and the view is called Data Binding.
Data Binding is a process that creates a connection between the application’s UI and the data. When the data changes its value, the UI elements that are bound to the data, will also change. Angular handles data binding by synchronizing the state of the view, with the data in the component.
Data-binding can be one-way, where a change in the state affects the view, or two-way, where a change from the view can also change the model.
The following types of bindings are supported by Angular:
- Interpolation
- Property Binding
- Event Binding
- Two-way binding
Interpolation and property binding
This article explains interpolation and property binding. The next upcoming article will explain event binding and two-way binding.
An Angular application starts with a component and the basis of data binding involves displaying data in a template rendered using a component. Let’s build a small component with a couple of fields and methods.
The component will be used to show the different binding techniques in this article as well as in the next upcoming article. The following snippet shows the component:
export interface Place {
city: string;
state: string;
country: string;
zipcode: string;
visited: boolean;
}
@Component({
selector: 'app-tour-city',
template: `<p>
tour-city works!
</p>`
})
export class TourCityComponent {
public city: string;
public locality: string;
public place: Place;
constructor() {
this.city = "London";
this.locality = "Heathrow";
this.place = {
city: 'Hyderabad',
state: 'Telengana',
country: 'India',
visited: true
};
}
}
The above snippet defines an interface and a component. The interface Place declares four fields to hold the values of different properties of a place.
A component is a TypeScript class with the decorator Component applied on it. The above component defines a selector and a template. The template is rendered on the page where the component would be used.
The component TourCityComponent has two public fields. One is city - a string field, and the other is place, which is declared using the interface Place, an object.
An object of the component class plays the role of data model for the template. Both of the fields defined in the class are accessible in the component. For now, the template of the component shows a hardcoded text.
Interpolation
Interpolation is a technique that allows the user to bind a value to a UI element.
Interpolation binds the data one-way. This means that when value of the field bound using interpolation changes, it is updated in the page as well. It cannot change the value of the field. An object of the component class is used as data context for the template of the component. So the value to be bound on the view has to be assigned to a field in the component class.
Figure 1 - Interpolation
To interpolate a piece of data, it must appear inside a UI element, such as {{city}}, or using curly braces.
The following snippet shows an interpolation expression to bind the field city of the TourCityComponent created earlier:
The city is: <strong>{{city}}</strong>
To see how it works, you may replace the template of the TourCityComponent with the above snippet.
When the component is rendered on a page with the above snippet in its template, it prints value of the field city on the view. The following figure shows the output of this snippet:
Figure 2 – Simple interpolation
The syntax of binding a field using double curly braces is called Binding Expression. Let’s try changing value of the city and see if the UI changes. For this, let’s change the value city after two seconds using setTimeout. Add the following snippet to the constructor of the component:
After making this change, when the page loads, it displays the city as London. And after two seconds, the name changes to Seattle.
The output of the page is shown in Figure 3:
Figure 3 - Modified value in interpolation
Say, we want to display the city in upper case letters. For this, we can add a getter property to the component to return the value in upper case.
A getter property addresses the need to get a modified version of an existing class field without creating a method. The following snippet defines this property:
get City(){
return this.city.toUpperCase();
}
This property can be used inside a binding expression. The following snippet demonstrates this:
The city is: <strong>{{City}}</strong>
This expression prints the value of city in upper case on the page, as shown below:
Note: Methods can also be used to bind data inside an interpolated expression. But we should be careful while using functions inside binding expressions. The function used in the expression should not change any values of the component. Changing values in the function used in binding will return two different values for the field when it is invoked two consecutive times in the same event loop. As Angular’s change detection is based on browser events, the binding expressions shouldn’t evaluate to two different values in the same event loop.
We can concatenate a static string value to value of the variable city inside the binding expression. The following snippet greets the city with ‘hello’:
<div>{{'Hello, ' + city}}</div>
We can concatenate multiple string fields in the expression as well. Let’s concatenate value of the field locality and the value of city in an expression. Change template of the component to the following:
The place is: <strong> {{locality +', '+ city}}</strong>
When rendered on the browser, it produces the following output:
Figure 5 – Concatenating fields in interpolation
Similar operations can be performed using numeric fields as well. Let’s add the following numeric fields to the component to explore their usage:
public num1: number = 5;
public num2: number = 100;
We can either display the values of these fields directly, perform simple arithmetic operations using fixed values or by using the value from another field in a binding expression. The following snippet shows a few examples using the above fields:
<div>{{num1+1}}</div>
<div>{{num1+num2}}</div>
<div>{{num1-num2}}</div>
<div>{{num1*num2}}</div>
<div>{{num2/num1}}</div>
We can bind values of the properties in an object using the binding expressions. In the TourCityComponent created above, we have the field place assigned with an object. Let’s display the different properties of the object on the page. For this, we need to include the following snippet in the template of the controller:
<div>City: {{place.city}}</div>
<div>State: {{place.state}}</div>
<div>Country: {{place.country}}</div>
<div>Visited: {{place.visited}}</div>
We can bind values of the properties in an object using the binding expressions. In the TourCityComponent created above, we have the field place assigned with an object. Let’s display the different properties of the object on the page. For this, we need to include the following snippet in the template of the controller:
<div>City: {{place.city}}</div>
<div>State: {{place.state}}</div>
<div>Country: {{place.country}}</div>
<div>Visited: {{place.visited}}</div>
We don’t always have the values available in the components. At times, we may need to wait for an HTTP request to complete before the value is assigned to the object. When the application waits for the HTTP request to complete, the above binding expressions will fail as value of the object would be undefined initially.
To mimic this behaviour, let’s assign value to the field place after two seconds using a setTimeout function. This has to be done in the constructor of the component.
constructor() {
setTimeout(() => {
this.place = {
city: 'Hyderabad',
state: 'Telengana',
country: 'India',
visited: true
};
}, (2000));
}
Upon loading the component on a page after this change, it will report an error saying “Cannot read property ‘city’ of undefined”. Angular won’t parse rest of the template after encountering an error, so we won’t see errors for other properties of the place object.
To avoid this error, we can check if the object has a value and then bind it:
<div>City: {{place && place.city}}</div>
Though it solves the problem, checking for presence of the value of a property in an object makes the expression cumbersome and hard to maintain.
A better way is to use the safe navigation operator(?.) to safely bind the inner fields. The following snippet uses the safe navigation property to bind name of the city:
<div>City: {{place?.city}}</div>
Sometimes, the object might be defined but the property may not be assigned with a value. The interface Place has a property named zipcode, but the component doesn’t assign a value to this property. If we bind this property on the page, it wouldn’t show any value. The following snippet binds the property:
<div>Zipcode: {{place.zipcode}}</div>
It produces the following output:
Figure 6 – Empty Zipcode
The result of the binding expression is the return value of the toString() method defined on the object bound in it. If we bind an object that doesn’t override the toString() method, we will see [object Object] on the page.
Let’s bind the object place on the page.
<div>{{place}}</div>
As the object place doesn’t implement the toString method, it produces [object Object]. Let’s modify the interface Place to declare this method and implement the method in the component. The following snippet shows the modified interface and the component:
export interface Place {
city: string;
state: string;
country: string;
zipcode: string;
visited: boolean;
toString(): string;
}
@Component({
selector: 'app-tour-city',
template: `<p>
tour-city works!
</p>`
})
export class TourCityComponent {
public city: string;
public locality: string;
public place: Place;
constructor() {
this.city = "London";
this.locality = "Heathrow";
this.place = {
city: 'Hyderabad',
state: 'Telengana',
country: 'India',
visited: true
};
this.place.toString = function(){
return `You are in the city ${this.city}, in the state of ${this.state} in ${this.country}.`;
};
}
}
Now the interpolation displays the string returned by the toString method. It is shown below:
Figure 7 – Place with toString method implemented
Interpolation can be used to assign values to attributes of the HTML elements. The syntax of the binding expressions remains the same, they are also evaluated on every browser event. Let’s add a field to the component and assign the success alert style from bootstrap, to it.
public alertClass: string = 'alert alert-success';
The following snippet sets this field to the class attribute of an HTML div element using interpolation:
<div class='{{alertClass}}'>The operation is successful!</div>
When this div is rendered on the browser, it appears like a success message.
You can explore these examples in this plunk: http://plnkr.co/edit/x6pAGzohlg51Qs5ozg1N?p=preview
Operations to be performed in interpolation
As we saw, interpolation can be used to bind any value on the page. We can perform some simple operations inside the expressions to modify the values. But it doesn’t mean that we can perform any JavaScript operation inside the binding expressions.
The following types of JavaScript operations are not allowed inside binding expressions:
- Assignments, increment (++) and decrement (--)
- Creating objects
- Bitwise operators (| and &)
As the binding expressions are evaluated on every browser event to keep the view in sync with the data, they should be simple and independent. Mixing the arithmetic expressions with interpolation could cause the following side effects:
- Increase complexity of the markup
- It may change the value of the field and that would add an inconsistency as it modifies the data in the same event loop and hence the modified value may not be displayed
- It hits performance as well, as interpolation has to be evaluated by the framework
- As it is not the recommended way, a change in the framework to disable this feature will break the applications
The values bound inside the binding expressions are evaluated when there is a change in state of the values and if the expression triggers one more change, it may enter an infinite loop. So keeping the expressions simple will reduce the time required to evaluate the expressions and ultimately make the application perform better.
Property Binding
Property binding is used to bind values to the DOM properties of the HTML elements. Like interpolation, property binding is a one-way binding technique. Property bindings are evaluated on every browser event and any changes made to the objects in the event, are applied to the properties.
DOM properties of the HTML elements shouldn’t be confused with HTML attributes of the elements. Every HTML element is represented as a JavaScript DOM object and every attribute of the HTML element is represented as a DOM property. For example, consider the following span element:
<span id="message" title="Message" style="font-style: italic; color: #FF0000;">This city is beautiful!</span>
We can read the text, title and the values of the style properties of the above span using the JavaScript DOM properties on the DOM object of the element. The following snippet reads these values and displays them in console:
let messageElem = document.querySelector('#message');
console.log("Text inside message element: " + messageElem.textContent);
console.log("Title of the message element: " + messageElem.title);
console.log("Styles of the message element: " + messageElem.style.fontStyle + " " + messageElem.style.color);
Observe the difference in the way the values are accessed. The text inside the HTML element is accessed using the textContent property, which doesn’t have a corresponding HTML attribute. The HTML attribute title has a DOM property with the same name. The HTML attribute style has an object in the DOM property with every individual style property represented as a property in the style object.
In an Angular application, we can bind the DOM properties using the values in the component. The property to be bound with the value can either be specified in square brackets [] or the property can be prefixed with bind-.
The following snippet shows both of these ways while binding the title of the span element:
<span [title]="titleText">This span has a dynamic title...</span>
<span bind-title="titleText">This span has a dynamic title...</span>
Both the approaches produce the same result. The first one uses punctuation (the square brackets) and the second one is canonical. We can say that the square brackets syntax is syntactic sugar. There is no difference in the way they are executed on a page.
The above snippet binds data to the title property of the span element. Once this page is rendered on a browser, we will see a little tooltip appearing when we hover the mouse over the span element.
Figure 8 - Binding title property
We can bind the HTML to be rendered in the element using the innerHtml property. The following snippet sets a sample HTML to a field in the component:
public html = 'This text is <b>data bound</b>';
Now we use it in a span element as:
<span [innerHtml]='html'></span>
It renders the HTML assigned to the field html in the component. Angular is smart enough to detect any malicious scripts in the data bound HTML and prevents it from executing. Let’s add a script tag to the field html to show an alert box.
public html = 'This text is <b>data bound</b>!<script>alert("This is dangerous!!!")</script>';
When this HTML is rendered on the page, we won’t see the alert box appearing on the page. This is because, Angular suppresses the execution of the script. The script elements are removed from the HTML and the content inside the script element is presented as plain text on the page. The above HTML produces the following output:
Figure 9 - Binding HTML with script tag
Binding styles of an element works in a slightly different way. We need to assign values to the individual style properties using the dot(.) operator. The following snippet shows an example of binding color of an element:
<span [style.color]='color'>This span is red.</span>
The field color is set to red in the component.
public color = 'red';
To bind data to multiple style properties, we need to bind them individually. Let’s set font size and font style to the span element we created earlier. The following snippet sets values to the fields which we will use for data binding:
public size = '20px';
public fontStyle = 'italic';
..and we bind them on the element as shown in the following snippet:
<span [style.color]='color' [style.font-size]='size' [style.font-style]='fontStyle'>This span is red.</span>
Notice the way we are referring to the style properties in the snippet. They are referred using dashed notation, which is the same way as we refer to them in CSS style classes or in the style attribute.
Alternatively, we can refer to them using camel case notation as well. The following snippet is the modified version of the above span element with camel case notation:
<span [style.color]='color' [style.fontSize]='size' [style.fontStyle]='fontStyle'>This span is red.</span>
To bind the CSS classes on an element, we can assign the list of classes to be applied to a string field in the component, and then assign it to the class property. We can keep changing value of the field to apply different classes to the element. The following snippet sets the Bootstrap classes to a string field to give a visual weight to the button:
public primaryButton = 'btn btn-primary';
We can assign this field to the class property just like we did to other properties.
<button [class]='primaryButton'>Submit</button>
To change the style of the button using data binding, we need to modify value of the field primaryButton in the component. Manipulating strings is a cumbersome and error prone process. We can avoid this using boolean fields for the CSS classes that have to be toggled based on a condition. Say, we need to make the above button default or primary based on value of a boolean variable named isPrimary. We can do the following:
<button class='btn' [class.btn-primary]='isPrimary' [class.btn-default]='!isPrimary'>Submit</button>
Since property binding is built on top of DOM properties and it doesn’t have any wrappers, it is extensible. If the browsers add new properties to the DOM objects, the framework would support them without adding code to support them.
You can explore these examples in this plunk: http://plnkr.co/edit/NU6crA5s584ICA29ch5L?p=preview
Operations to be Performed in Property Binding
The expressions assigned to the property bound fields can perform similar functionalities as the binding expressions in interpolation. As values assigned to the properties may change in a given event loop, they are evaluated on every event loop. They should just return the right value for the binding and shouldn’t change state of any of the objects.
The set of operations to be performed in a property binding expression are same as the set of rules discussed for interpolation in the previous section.
Conclusion
Interpolation and property binding provide an easy way to bind data or functions in the components with almost any element or attribute in the view. As discussed in this tutorial, there are a few points to keep in mind while composing binding expressions. The next upcoming tutorial will discuss the other flavors of bindings - Event and Two-way binding.
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