Over the recent months, Angular has been evolving rapidly, introducing new features and a ton of improvements, many of these to improve 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 with 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" />
Code language: HTML, XML (xml)
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;
}
Code language: TypeScript (typescript)
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) {}
}
Code language: TypeScript (typescript)
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: the new HostAttributeToken class.
Inject an Attribute using HostAttributeToken class
With 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') );
}
Code language: JavaScript (javascript)
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 feel free to contact me for any. 👋
Then, if you really liked it, share it among your community, tech bros, and whoever you want. 👋😁