Jerry Gagliano logo
My Resume
← Go Back

Directive Composition API in Angular 15

Angular

Angular version 15 is around the corner with new features coming up. The particular feature I want to share is the directive composition api and how we can implement it.

This feature allows you to create a standalone directive without the need to be rendered in the template. Developers were demanding this feature which I had no idea which is good to see. Here is an article for more details Directive composition API

What caught my eye about this feature is using the takeUntil pattern with a directive. Those of you who don't know about this particular pattern, it's basically using a Subject observable. When the component is destroyed, the observable is emitted and unsubscribes the observable. This is a common pattern used in Angular app development but not in a well-structured way.

Here is an example without the directive composition API:

@Component()
export class YourComponentName implements OnDestroy {
  private destroy$ = new Subject<void>();

  constructor() {
    AnyObservable$.pipe(
      takeUntil(this.destroy$)
    ).subscribe((params) => {
      ...your code here
    });
  }

  ngOnDestory() {
    this.destroy$.next();
  }
}

As we see, the observable will unsubscribe once the component is destroyed and will emit the Subject observable. If we had hundreds of components that implement this specific pattern. Lots of repeated code which is not ideal!

Here is an example of using directive composition API composing with a directive:

@Directive({ standalone: true }) // standalone is needed
export class DirectiveName implements OnDestroy {
  private destroy$ = new Subject<void>();

  get pipe() {
    return pipe(takeUntil(this.destroy$));
  }

  ngOnDestory() {
    this.destroy$.next();
  }
}

Here we import the directive using the hostDirectives property

@Component({
  hostDirectives: [DestroyedDirective]
})
export class ComponentName implements OnInit {
  private untilDestroyed = new inject(DestroyedDirective).pipe;

  constructor() {
    AnyObservable$.pipe(
      this.untilDestroyed
    ).subscribe(() => {
      ...will have code here
    });
  }
}

As we see much cleaner and code is centralized. If we need to modify the takeUntil operator or add logic we would have one common file.

One argument we might have, directives are UI based elements only. This is true, but you're still actually managing functionality in the component UI. The other argument is why not just use a service? I prefer not to use services much. Services are used mainly to create methods containing endpoint calls or without UI component interaction. If you use a state management library like NGXS, services are much less needed.

Final Thoughts

Here it is! A quick example of how to structure your takeUntil's using the new directive composition API. This is just one idea and I am sure so many other developers will use this feature in different ways. If other developers have other ideas, please email me with examples as I am curious to expand my knowledge about this feature.

Cheers!

Thank you for taking the time in reading this blog. If you find any invalid information or want to add more this blog you may contact me at:

jerrygag@gmail.com