Understanding hostDirectives Declaration Inside the @Component Decorator

Gili Yaniv
4 min readAug 9, 2023

--

In Angular, the @Component decorator plays a crucial role in defining the structure and behavior of components. It allows developers to create reusable and modular pieces of user interface, encapsulating the template, styles, and logic into a single unit. While the @Component decorator offers a range of options to customize components, one powerful yet lesser-known feature is hostDirectives. In this article, we will explore the hostDirectives property and its significance in Angular applications with code examples.

What is hostDirectives?

The hostDirectives property is an advanced feature in Angular's @Component decorator (Introduced in Angular 15. 2) that allows developers to declare directives to be used on the host element of a component. Host elements are the elements representing the component in the DOM tree. With hostDirectives, we can dynamically apply directives to the host element, enabling additional functionalities or behavior specific to the component.

Syntax

The syntax for using hostDirectives inside the @Component decorator is as follows:

@Component({
// Other component properties (selector, template, styleUrls, etc.)
hostDirectives: [{
// Directive declarations to be applied on the host element
}]
})

Use Cases

1. Styling the Host Element

The hostDirectives property can be used to apply styling directives directly to the host element. For example, let's say we want to apply a custom directive called FancyBorderDirective to the host element to add a fancy border to the component.

import { Directive, ElementRef, Renderer2 } from '@angular/core';

@Directive({
selector: '[appFancyBorder]'
})
export class FancyBorderDirective {
constructor(private el: ElementRef, private renderer: Renderer2) {
this.renderer.setStyle(this.el.nativeElement, 'border', '2px solid blue');
this.renderer.setStyle(this.el.nativeElement, 'padding', '10px');
this.renderer.setStyle(this.el.nativeElement, 'border-radius', '5px');
}
}

Now, we can use the appFancyBorder directive in the hostDirectives property of our component:

@Component({
selector: 'my-custom-component',
standalone: true,
imports: [CommonModule],
template: `
<!-- My Cool Component template -->
`,
hostDirectives: [FancyBorderDirective],
})
export class CustomComponent {
}

By doing this, our CustomComponent will have the FancyBorderDirective applied to its host element, making it visually stand out with a blue border and some padding.

2. Applying Behavior to the Host Element

The hostDirectives property is not limited to just styling. You can also use it to attach behavior to the host element. Let's assume we have a directive called TooltipDirective that displays a tooltip when hovering over an element.

import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
selector: '[appTooltip]'
})
export class TooltipDirective {
constructor(private el: ElementRef) {}

@HostListener('mouseenter')
showTooltip() {
// Show the tooltip logic
}

@HostListener('mouseleave')
hideTooltip() {
// Hide the tooltip logic
}
}

Now, we can use the appTooltip directive in the hostDirectives property of our component:

@Component({
selector: 'app-tooltip-component',
template: '<button appTooltip>Hover over me!</button>',
hostDirectives: [TooltipDirective]
)
export class TooltipComponent { }

By doing this, our TooltipComponent will have the TooltipDirective applied to its host element (the button), and the tooltip behavior will be triggered when hovering over the button.

3. Dynamically Controlling Host Directives

In some cases, we might want to dynamically control the application of host directives based on certain conditions. This can be achieved by binding different inputs to thehostDirectives property.

@Component({
selector: 'my-custom-component',
standalone: true,
imports: [CommonModule],
template: `
<!-- My Cool Component template -->

`,
hostDirectives: [
{
directive: FancyBorderDirective,
inputs: ['isFancyBorderEnabled'], // <---
},
],
})
export class CustomComponent {
}

In this example, we have a component that applies the FancyBorderDirective to its host element conditionally based on the value of the applyFancyBorder property. We can use the isFancyBorderEnabled method to dynamically switch the application of the directive.

@Directive({
selector: '[appFancyBorder]',
standalone: true,
})
export class FancyBorderDirective implements OnChanges {
@Input() isFancyBorderEnabled: boolean = false;
constructor(private el: ElementRef, private renderer: Renderer2) {}

ngOnChanges({ isFancyBorderEnabled: { currentValue }}: SimpleChanges) {
if (currentValue) {
this.renderer.setStyle(this.el.nativeElement, 'border', 'none');
this.renderer.setStyle(this.el.nativeElement, 'padding', '0');
this.renderer.setStyle(this.el.nativeElement, 'border-radius', '0');
} else {
this.renderer.setStyle(this.el.nativeElement, 'border', '2px solid blue');
this.renderer.setStyle(this.el.nativeElement, 'padding', '10px');
this.renderer.setStyle(this.el.nativeElement, 'border-radius', '5px');
}
}
}

@Component({
selector: 'my-custom-component',
standalone: true,
imports: [CommonModule],
styles: [
`
display: block;
`,
],
template: `
<p>Content to be wrapped with a fancy border</p>
`,
hostDirectives: [
{
directive: FancyBorderDirective,
inputs: ['isFancyBorderEnabled'],
},
],
})
export class CustomComponent {}

@Component({
selector: 'my-app',
standalone: true,
imports: [CommonModule, CustomComponent],
template: `
<my-custom-component [isFancyBorderEnabled]="isEnabled"></my-custom-component>

<button (click)="toggleDisabled()">Click Here</button>
`,
})
export class App {
isEnabled = true;

toggleDisabled() {
this.isEnabled = !this.isEnabled;
}
}

The example above can be found here.

Conclusion

The hostDirectives property inside the @Component decorator is a powerful and flexible feature that allows developers to customize the behavior and appearance of components by applying directives directly to their host elements. This capability opens up numerous possibilities for creating reusable and dynamic components in Angular applications. By leveraging hostDirectives, developers can build more modular and sophisticated components that enrich the user experience and improve the maintainability of the codebase.

--

--

No responses yet