How to Programmatically Render Directives in Angular +15
Creating a directive in Angular without using the template, but dynamically using code was difficult until version 15. But with the help of the Directive composition API, we can make a workaround to dynamically create a directive.
Angular offers different ways to programmatically render components, you can read more about this in the article Programmatically rendering components.
However, unfortunately, Angular does not provide any built-in way to dynamically create a directive. Even if a component class extends a directive, these methods are not designed for dynamically creating directives.
There exist two options for dynamically creating a directive: one that utilizes the Directive Composition API, and alternatively, one that instantiates the class and handles the lifecycle and change detection phases manually.
There is no need to explain why it is a total hassle and non-intuitive to instantiate the directive class and bind it to the component's lifecycle and change detection.
However, the process can become very complicated when dealing with directives from third-party packages, where you have limited control over their implementation. For instance, using the RouterLink directive can be a complex task.
Now, let's delve into the concept of Directive Composition API. It is recommended to familiarize yourself with the documentation first and then revisit the tutorial.
Therefore, Directive Composition API allows us to attach directives to components. An innovative approach I came up with was to wrap the RouterLink directive in a component.
import {Component, ViewEncapsulation} from '@angular/core';
import {RouterLink} from '@angular/router';
@Component({
selector: 'a',
template: '<ng-content></ng-content>',
standalone: true,
encapsulation: ViewEncapsulation.None,
hostDirectives: [
{
directive: RouterLink,
inputs: ['routerLink', 'fragment', 'queryParamsHandling', 'queryParams'],
},
],
})
export class AnchorComponent {}
As you can see, we add the directive to hostDirectives
and connect the directive's inputs to the component's inputs.
Now let's try to programmatically render.
import {Component, ViewContainerRef, ViewChild, OnInit, Renderer2} from '@angular/core';
import {AnchorComponent} from './anchor';
@Component({
selector: 'app',
standalone: true,
template: ` <ng-container #vc></ng-container> `,
})
export class App implements OnInit {
@ViewChild('vc', {static: true, read: ViewContainerRef}) vc!: ViewContainerRef;
constructor(private readonly renderer: Renderer2) {}
ngOnInit(): void {
const comp = this.vc.createComponent(AnchorComponent, {
projectableNodes: [[this.renderer.createText('It works!!')]],
});
comp.setInput('routerLink', '/');
comp.changeDetectorRef.detectChanges();
}
}
In this Stackblitz you can see how it works 馃槂!
Happy codding!
How Much Does A Website Cost?
Learn how to calculate the price of a website based on a general formula.
Professional Website for Business: Boost Credibility in 2024
Discover how the UI/UX, speed, and fluidity of a business website contribute to its professional image in the eyes of users.
Small Business Web Site Hosting: How to Choose One
Learn how to select the right web hosting provider for your small business and optimize costs to maximize your savings.
Lead Generation Landing Page: Why and How?
Learn how to generate leads using a landing page. In this article, you will understand what is a landing page and a few tips for boosting leads.