DEV Community

Cover image for From @Attribute to HostAttributeToken: A Modern Angular DI Pattern
vetriselvan Panneerselvam
vetriselvan Panneerselvam

Posted on

From @Attribute to HostAttributeToken: A Modern Angular DI Pattern

Hey devs! đź‘‹

As promised, we're continuing our series on Angular decorators. But today, we’re doing something a bit different. A friend recently pointed me to a more modern and DI-friendly alternative to the traditional @Attribute decorator—say hello to HostAttributeToken.

Let’s dive into how this new approach works and how you can use it to write cleaner, more testable Angular code.

What is HostAttributeToken?

HostAttributeToken allows you to inject static attribute values from the host element in a more flexible, testable, and dependency injection (DI)-friendly way.

In older Angular versions, you’d use the @Attribute decorator for this. While that works fine, HostAttributeToken provides several advantages — especially when working with standalone components or modern DI patterns.

Syntax

new HostAttributeToken('attrName');
Enter fullscreen mode Exit fullscreen mode

Example: Replacing @Attribute with HostAttributeToken

We’ll reuse an example we discussed earlier using the @Attribute decorator — but this time, we’ll refactor it using HostAttributeToken.

Both approaches achieve the same functionality, but HostAttributeToken allows the attribute value to be injected using the inject() function, outside of the constructor.

Directive: FontType

import { AfterViewInit, Directive, ElementRef, HostAttributeToken, inject, OnInit, Renderer2 } from '@angular/core';

@Directive({
  selector: '[fontType]'
})
export class FontType implements OnInit, AfterViewInit {
  private renderer = inject(Renderer2);
  private el = inject(ElementRef);
  public font: string = inject(new HostAttributeToken('font'));

  constructor() {
    console.log(this.font);
  }

  ngOnInit(): void {
    switch (this.font) {
      case 'italic':
        this.renderer.setStyle(this.el.nativeElement, 'color', 'red');
        break;
      case 'bold':
        this.renderer.setStyle(this.el.nativeElement, 'color', 'green');
        break;
      case 'underline':
        this.renderer.setStyle(this.el.nativeElement, 'color', 'orange');
        break;
      default:
        console.log('Font not provided');
    }
  }

  ngAfterViewInit(): void {
    console.log('Before changing the attribute value:', this.font);
    this.renderer.setAttribute(this.el.nativeElement, 'font', 'some_random_value');
    console.warn('After changing the attribute value:', this.font);
  }
}
Enter fullscreen mode Exit fullscreen mode

Component Usage

import { Component } from '@angular/core';
import { FontType } from '../../directive/role';

@Component({
  selector: 'app-about',
  standalone: true,
  imports: [FontType],
  template: `
    <h1><u>About Me</u></h1>
    <p>
      I’m a <b>frontend developer</b> and
      <b fontType font="bold">freelancer</b> passionate about building
      beautiful, responsive, and user-friendly web interfaces.
    </p>
    <p>
      I specialize in <b><u fontType font="underline">HTML</u></b>,
      <b><u fontType font="underline">CSS</u></b>,
      <b><u fontType font="underline">JavaScript</u></b>,
      and modern frameworks like <b>React</b> and <b>Vue</b>. I enjoy turning
      complex problems into simple, elegant solutions.
    </p>
    <p>
      <i fontType font="italic">I believe that great design is just as important as great code</i>,
      and I’m always exploring <u>new technologies</u> and tools to enhance user experience.
    </p>
    <p>
      Whether it’s building from scratch or improving an existing project,
      I’m ready to help.
      <b><i><u>Let’s create something amazing together!</u></i></b>
    </p>
  `,
  styleUrls: ['./about.scss'],
})
export class AboutComponent {}
Enter fullscreen mode Exit fullscreen mode

Output

Image description

Pros and Cons of HostAttributeToken

âś… Pros:

  • DI-friendly: Works seamlessly with inject(), even outside constructors.
  • Flexible: Compatible with standalone components and modern DI patterns.
  • Testable & Mockable: Easily overridden in unit tests or custom providers.
  • Versatile: Usable in factories, services, and other DI contexts.

⚠️ Cons:

  • Static Only: Still reads a static value from the attribute — it’s not reactive to changes made after initialization.

Conclusion

HostAttributeToken is a modern and powerful replacement for @Attribute. If you're embracing Angular’s latest DI improvements, this is definitely a pattern worth adopting.

Have you tried this approach yet? Let me know your thoughts and experiences in the comments below! 🚀

✍️ Author: Vetriselvan

👨‍💻 Frontend Developer | Code Lover | Exploring Angular’s future

Top comments (0)