Understanding Directive composition API in Angular

Directive composition API in Angular 15

Angular team introduced a new feature called “Directive composition API” in Angular 15 Version.

It’s one of the most requested feature from the Angular community since 2016. (From Angular 2 onwards)

Directive composition API example

Let’s understand what is this directive composition in Angular.

We will create simple directive in Angular which apply the CSS color to an Angular component.

ng generate directive redColor

And in the directive definition and the below code.

import { Directive } from '@angular/core';

@Directive({
  selector: '[appRedcolor]',
  host: { style: 'color:red' },
})
export class RedcolorDirective {
  constructor() {}
}

Now apply the directive to a component in Angular.

ng generate component testdirective

And in the component HTML add the redColor directive.

<app-testdirective appRedColor></app-testdirective>

//Inside testdirective.component.html

<p> Hello I am displayed in red color using directive</p>

Now the text inside testdirective component will be displayed in red color.

Now using Directive composition API we can directly add the directive inside component declaration using hostDirectives property.

import { Component } from '@angular/core';
import { RedColorDirective } from '../red-color.directive';


@Component({
  selector: 'app-testdirective',
  templateUrl: './testdirective.component.html',
  styleUrls: ['./testdirective.component.scss'],
  hostDirectives:[RedColorDirective]
})
export class TestdirectiveComponent {
}

Now no need to add appRedColor directive to the component.

<app-testdirective></app-testdirective>

But here is the catch, you will get an error saying Host directive must me standalone

error NG2014: Host directive RedColorDirective must be standalone

hostDirectives:[RedColorDirective]

That means we can add only standalone directives in hostDirectives array.

Let’s make our directive stand alone by adding standalone property inside directive declaration and remove the definition from the app.module.ts file.

import { Directive } from '@angular/core';

@Directive({
  selector: '[appRedColor]',
  host:{'style': 'color:red;'},
  standalone: true
})
export class RedColorDirective {

  constructor() { }

}

Now the text inside testdirective component will be displayed in red color.

<app-testdirective></app-testdirective>

And our code looks simple without adding an extra directive in component tag.

We can add more than one directive inside hostDirectives property.


@Component({
  selector: 'app-testdirective',
  templateUrl: './testdirective.component.html',
  styleUrls: ['./testdirective.component.scss'],
  hostDirectives:[RedColorDirective,HeightDirective,FontStyleDirective,......]
})
export class TestdirectiveComponent {
}

We can add hostDirectives inside an another directive as well.

Directive Composition API inside directives

Let’s create multiple directives each with specific functionality.

ng generate directive height --standalone=true
ng generate directive width --standalone=true
ng generate directive fontBold --standalone=true
ng generate directive border --standalone=true
import { Directive } from '@angular/core';

@Directive({
  selector: '[appHeight]',
  host:{'style': 'height:100px;'},
  standalone: true
})
export class HeightDirective {
  constructor() { }
}

Now we will create a directive and add above standalone directives inside hostDirectives array.

ng generate directive style

Add the required directives as shown below.

import { Directive } from '@angular/core';
import { BorderDirective } from './border.directive';
import { FontBoldDirective } from './font-bold.directive';
import { HeightDirective } from './height.directive';
import { RedColorDirective } from './red-color.directive';
import { WidthDirective } from './width.directive';

@Directive({
  selector: '[appStyle]',
  hostDirectives:[RedColorDirective,FontBoldDirective,HeightDirective,WidthDirective,BorderDirective]
})
export class StyleDirective {

  constructor() { }

}
<div appStyle>
    Hello Styles are added using directive composition API
</div>

Chain of Host Directives

Instead of adding host directives in one array we can create chain of host directives.

ng generate directive size --standalone=true

Inside size directive

@Directive({
  selector: '[appSize]',
  standalone: true,
  hostDirectives:[WidthDirective]
})

//In the width directive chain the height directive

@Directive({
  selector: '[appWidth]',
  host:{'style': 'width:500px;'},
  hostDirectives:[HeightDirective],
  standalone: true
})

// In the height directive chain the border directive

@Directive({
  selector: '[appHeight]',
  host:{'style': 'height:100px;'},
  standalone: true,
  hostDirectives:[BorderDirective]
})

// Border Directive

@Directive({
  selector: '[appBorder]',
  host:{'style': 'border:1px solid;'},
  standalone: true
})

Now we can directly the size directive inside hostDirectives of the component.

@Component({
  selector: 'app-testdirective',
  templateUrl: './testdirective.component.html',
  styleUrls: ['./testdirective.component.scss'],
  hostDirectives:[SizeDirective]
})

Real use cases

I have added only simple examples to get an idea about hostDirectives and directive composition API in Angular 15.

More real world use cases can be found at the following github issue.

directive composition API.

Github Source code

Here is the source code for the demo of directive composition API.

host-directives