DEV Community

Gaëtan Redin
Gaëtan Redin

Posted on • Originally published at Medium on

Angular 15: hostDirectives

How to avoid duplications and to keep access to properties

Hey, as you know, Angular 15 has been come with a new great feature: hostDirectives.

There are already many articles about it but I never read something about how to keep access to the directives properties yet. I will focus on an explicit example that will all know: disabled state.

Let’s start with an example:

@Component({
  selector: '...',
  host: {
    ...
    '[class.my-disabled-class]': 'disabled',
    '[attr.disabled]': 'disabled || null',
    '[attr.aria-disabled]': 'disabled || null',
    ...
  },
  template: `...`
})
class MyComponent {
  @Input() public disabled = false;

  // many other stuffs
}
Enter fullscreen mode Exit fullscreen mode

This little piece of code is often duplicated. Sometimes, people use mixins to be DRY but you still have to repeat the host part.

So how to do better?

First, we will create the DisabledState directive like as follow:

@Directive({
  selector: '[myDisabledState]',
  standalone: true, // available since Angular 14
  host: {
    '[attr.disabled]': 'disabled || null',
    '[attr.aria-disabled]': 'disabled || null',
    '[class.rc-disabled]': 'disabled',
  },
})
export class DisabledStateDirective {
  @Input() public disabled = false;
}
Enter fullscreen mode Exit fullscreen mode

And now, we can simplify our component like this:

@Component({
  selector: '...',
  host: {
    ...
  },
  hostDirectives: [{
    directive: DisabledStateDirective,
    inputs: ['disabled'],
  }],
  template: `...`
})
class MyComponent {
  // many other stuffs
}
Enter fullscreen mode Exit fullscreen mode

More readable right? And also, better separation of concerns. One point, I loose the access to the disabled property. How to know in my component if it’s disabled or not? Thanks to the great Angular, it’s really easy to do it:

@Component({
  selector: '...',
  host: {
    ...
  },
  hostDirectives: [{
    directive: DisabledStateDirective,
    inputs: ['disabled'],
  }],
  template: `...`
})
class MyComponent {
  private readonly _disabledState: DisabledStateDirective = inject(DisabledStateDirective, { self: true });

  public myFunction(): void {
    if (this.disabledState.disabled) {
      ...
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

We can just use the inject method to get the DisabledStateDirective , we use the self: true to simplify the search to it.

Et voilà (I’m still french sorry).

I hope this little example will help someone to simplify his code et to write more readable code.

Thanks for reading.

Top comments (0)