Angular HostAttributeToken: the new way to inject attributes

Angular HostAttributeToken: the new way to inject attributes

Over the latest months Angular has been evolving rapidly, introducing new features and a ton of improvements, many of these with the aim of improving maintainability and performance.

In this article I want to introduce you to the latest addition brought by Angular v17.3.0: the new HostAttributeToken class.

This new API allows you to inject host attributes using the inject() function, similar to the functionality of the @Attribute decorator.

The @Attribute decorator is perhaps the lesser-known Angular decorators.
Therefore, before delving into how the HostAttributeToken class works, let’s take a moment to review the fundamentals.

@Attribute: do you really need an input?

Let’s start from a simple scenario in which you want to develop a component requiring a configurable property.

Specifically, you want to provide this property as a constant string literal, because it will not change throughout runtime:

<my-divider size=“small” />

What you would normally do is to create an input for that property:

import { Component, Input } from @angular/core;

export type DividerSize = small | big;

@Component({
selector: my-divider,
template: <hr [class]=”size” />,
standalone: true,
})
export class MyDivider {
@Input() size: DividerSize;
}

Which is fine and works quite well. Perhaps too much…

By creating an input, you are instructing Angular to create a binding to that property and check it during each change detection cycle.

That is really excessive, you only need that property to be checked once during component initialization. 🤯

To make this more performant you can instead inject the host-element attribute in the constructor thanks to the @Attribute decorator:

import { Attribute, Component } from @angular/core;

export type DividerSize = small | big;

@Component({
selector: my-divider,
template: <hr [class]=”size” />,
standalone: true,
})
export class MyDivider {
constructor(@Attribute(size) size: string) {}
}

Using @Attribute, Angular will read the value only once and never again.

Note: This approach works as well with Directives, feel free to give it a shot!!!

Now that we have covered the basics, let me introduce you to the main topic of this article: new HostAttributeToken class.

Inject an Attribute using HostAttributeToken class

Since the release of Angular 14 there is now a cleaner approach to inject providers without using the constructor class: the inject() function.

Up until now, this inject() function allowed to inject easily components, directives and pipes, but it was missing a method to inject host attributes.

And that’s precisely why the HostAttributeToken class was introduced:

import { Component, HostAttributeToken, inject } from @angular/core;

export type DividerSize = small | big;

@Component({
selector: my-divider,
template: <hr [class]=”size” />,
standalone: true,
})
export class MyDivider {
size: string = inject( new HostAttributeToken(size) );
}

By injecting an HostAttributeToken class within the inject function, you get the corresponding host-element attribute value.

This new API works similarly to @Attribute, with a notable difference: instead of returning null when the attribute is missing, it throws an error.

This change was made to align the behavior with other injection tokens.

Thanks for reading so far 🙏

I’d like to have your feedback so please leave a comment, like or follow. 👏

Then, if you really liked it, share it among your community, tech bros and whoever you want. And don’t forget to follow me on LinkedIn. 👋😁

Leave a Reply

Your email address will not be published. Required fields are marked *