You probably shouldn't do this. It's a bad idea. So anyway here's the code.
@Directive()
export class Fragment {
nativeElement;
comment;
childNodes
constructor() {
this.nativeElement = inject(ElementRef).nativeElement;
this.comment = document.createComment(
` ${Object.getPrototypeOf(this).constructor.name} `
);
}
ngAfterViewInit() {
const { nativeElement, comment } = this;
const parent = nativeElement.parentElement;
this.childNodes = Array.from(nativeElement.childNodes)
parent.insertBefore(comment, nativeElement);
for (const node of this.childNodes) {
parent.insertBefore(node, nativeElement);
}
nativeElement.remove();
}
ngOnDestroy() {
this.comment.remove();
for (const node of this.childNodes) {
node.remove()
}
}
}
This will replace the host element of a directive with whatever is inside it. It even leaves a nice little comment behind.
To see how it's used let's create a provider that will pass through values from the template.
@Directive({
selector: 'MyProvider',
})
export class MyProvider extends Fragment {
@Input() value;
}
We're using TitleCase here to distinguish it from rendered DOM elements. Remember that Angular selectors are case sensitive.
Now we can import the directive and use it in a template.
<MyProvider [value]="name">
<hello></hello>
</MyProvider>
The hello
component can then inject the provider to read its value.
@Component({
selector: 'hello',
template: `<h1>Hello {{provider.value}}!</h1>`,
styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent {
provider = inject(MyProvider);
}
See it in action on StackBlitz
When we look at the DOM we can see that the host element is replaced with a HTML comment.
Is This a Good Idea?
Probably not. All it does is add some sugar to <ng-container>
in a not-very efficient way. There are probably other side effects I'm not aware of.
Can you think of a use case?
Top comments (0)