Angular 2 Property and Attribute binding explained in depth

This is a simple topic, but if it seems a bit foreign to you don't let that dishearten you. I have been working with various front end frameworks and been doing DOM manipulation for years and this is a subject that gave me a bit of a mind twist. I knew what it did technically but I guess the syntax gave me some mental road blocks for some reason that kept me from really getting it fully. Don't worry though, we're about to wade through this swamp. Grab a Redbull, roll up your sleeves, and refill your mouse batteries and let's go.

HTML attributes vs Properties in the DOM

Let's take an example case and examine it:

<input id="username" type="text" name="username" value="Mr. Barrick">

Here we have a standard HTML element with some attributes. These attributes are just strings. One might ask, how are these values related to properties, and what does it mean when you bind to a property in Angular? One step at a time, let's tackle the first question.

Standard Element Attributes

Standard element attributes are only strings that you write when you create your markup. They usually are just attatched to provide a default or initial value. You can think of them as static values.They aren't dynamic, they aren't exciting, they don't live life to the edge.

Element Properties

Properties on the other hand, live a fast pace exiting life, they can be the result of expressions, functions, change at runtime, ect. In other words, they can be dynamic.

When we talk about a webpage and we talk about javascript we almost always end up talking about something called the DOM. This stands for the document object model. The premise of this is that a web page, aka a document, is made up of a collection of objects. That's how javascript sees it anyways. When we look at a page's source, we are looking at the browser's rendered interpretation of that model. If we want to work with things from a programatic standpoint instead of just from a markup point of view, we can grab any of those elements on the page with javascript. Those elements then can be worked with like standard objects, and standard objects have properties.

The moment of truth: When attributes become properties

When the browser reads your markup it converts the HTML to DOM nodes. Those elements become objects, DOM nodes, and the attributes become properties. There isn't always a one to one conversion. Take for instance an attribute of class. It doesn't convert to a property of class, but instead it becomes classList.

An object's property can be almost anything. You can have a string, a function, another object, almost anything. Inversely an attribute is just a string. Angular has a declarative syntax that let's you bind directly to an element's properties and it calls this syntax property binding. It looks a little something like this:

<input id="username" type="text" name="username" [value]="'paul1234'">

The snippet above binds the string paul1234 to the value property of the input.

That's not the thing thats so magical though. Angular's main purpose or property binding is to let you pass data from your component instance, directly to the template.

Angular's main purpose or property binding is to let you pass data from your component instance, directly to the template.

If I were to leave off the inner quotes above then the input would be looking for a property of my component instance called paul1234. This is pretty cool because it means that I can have a user object in my component instance and reference that objects' values directly in my html like so:

<input id="username" type="text" name="username" [value]="user.username">

Let's look at a even more Angular-y example. Take these two cases and consider what the difference is:

<a routerLink="/home">Home</a>


<a [routerLink]="homePath">Home</a>

So knowing what we know now, we are armed with the info we need to answer this question now right? In the first example, we are setting an attribute, routerLink to a static string path home in our template. In the second example, we are setting a property equal to the property homePath in our component instance.

But wait, there's more!
By binding to a property as opposed to a string, we can pass dynamic values to our router and we are able to take advantage of what Angular calls the link parameters array and it looks like this:

<a [routerLink]="['/home', homeChildPath, {'someVar': true}]">Home</a>

This link would resolve to something like: /home/myHomeChildPath;someVar=true

This expressive style of writing your routes allows for some really interesting combinations and gives you a lot of flexibility and power for making your routing style fit whatever you needs case may be.

Attribute Binding

So let's recap. Using the bracket syntax, [ ], you can bind component properties directly to an elements' properties right from your template. What happens though, when you need to bind to a property of an HTML element that doesn't exist or doesn't translate directly from an attribute to a property? Something like this for instance:

<input [data-username]="" type="text">

When this happens you get this lovely error:

Template parse errors:
Can't bind to 'data-username' since it isn't a known native property

The solution to this is use property binding syntax still, but to start it with the attr prefix. This tells Angular just to bind to an attribute instead of trying to bind it to an elements property and is this is what Angular calls attribute binding. That change would look like this:

<input []="" type="text">

Voila! Problem solved.


I hope this has been a little illuminating for some people. Using property and attribute binding you can do all kinds of nifty things. Angular doesn't limit you to just property and attributes though. You can bind to classes, styles, and more. I encourage you to explore the docs a bit and see more examples of the kind of simplistic power that Angular lays right at your feet.


Two-Way Data Binding in Angular
Angular Docs: Property Binding
Properties and Attributes in HTML
Difference between 'routerLink' and [routerLink]