Attribute vs Property In Angular

The concept of Attributes vs Properties in Angular can get confusing at times. Mostly because often there attributes and properties with the exact same name. If we take a simply example, using an input html tag such as :

<input type="text" id="nameInput" value="Jim">

Here we have an input HTML tag that sets a value of “Jim”. This sets the initial value of this input to “Jim”. If a user edits this value and changes it to “Jane”, we can observe two things :

  • If we use getAttribute(‘value’) on this input, it will return our initial value of “Jim” not “Jane”.
  • If we fetched the DOM property value for this input, it would be our new value of “Jane” not Jim.

This simplifies things for us a little because we can then boil down attributes vs properties in Angular to the broad concept of :

  • Attribute – Represents the initial value and does not change.
  • Property – Represents the current value and can change.

In Angular, we can go further to describe attributes as belonging to HTML. However once a page is rendered (broadly speaking), an attribute does not change and is purely used in the initial rendering process. Whereas a property is almost a “binding” to the current value, including the initial value set by an attribute.

Things can get a little complex in our heads when trying to understand whether we should use a property or attribute. But for the most part, we will be using properties. That’s because many HTML Attributes have a 1 to 1 mapping with DOM properties. Therefore getting/setting a property on an HTML element will generally speaking be fine.

There are however exceptions to this rule. Notable elements that have attributes, that do not have properties. A good example of this is the colspan attribute of a table cell like so :

<td [colspan]="4"></td>

We are passing in a hardcoded value of 4 here, but we may also pass through something like a property of our component :

<td [colspan]="columnCount"></td>

Either way, we would receive the following error :

Can't bind to 'colspan' since it isn't a known property of 'td'.

This is because colspan only exists as an attribute (And it’s important to note that in the error message, specifically it is talking about a known property). You would even get this message if you were just using string interpolation like so :

<td colspan="{{columnCount}}"></td>

However Angular gives us a way to set an attribute value, and avoid using properties. That is like so :

<td [attr.colspan]="columnCount"></td>

This sets only the attribute, and not the property. What this does tell us though is that colspan is not “designed” to be changed after the initial render (Of course, in modern times there are always exceptions to this rule).

Other common examples of attributes that don’t have corresponding properties would be all aria-* tags.

What about the other way around? Do properties exist that don’t have corresponding attributes? Of course! Plenty. Really any custom property you add to a component is a property that exists in the DOM but does not exist in HTML attributes!

Hopefully this goes some way to explaining why we have attributes and properties, and what their subtle differences in Angular are.

Leave a Reply

Your email address will not be published.