Let's try this
Firstly, we create a DomService
to help you attach/detach component from container
import {
ApplicationRef,
ComponentFactoryResolver,
ComponentRef,
EmbeddedViewRef, Inject,
Injectable,
InjectionToken,
Injector
} from '@angular/core';
import {ComponentPortal} from '@angular/cdk/portal';
import {DOCUMENT} from '@angular/common';
export const MY_TOKEN = new InjectionToken<{}>('MY_TOKEN');
@Injectable({
providedIn: 'root'
})
export class DomService {
constructor(
@Inject(DOCUMENT) private document: Document,
private componentFactoryResolver: ComponentFactoryResolver,
private appRef: ApplicationRef,
) {
}
private _createInjector(useValue): Injector {
return Injector.create({
providers: [{provide: MY_TOKEN, useValue}]
});
}
createComponent(
component: any,
appendTo: Element,
componentProps: {},
wrapperClass: string
): ComponentRef<unknown> {
const componentRef = this.componentFactoryResolver
.resolveComponentFactory(component)
.create(this._createInjector(componentProps));
this.appRef.attachView(componentRef.hostView);
const domElem = (componentRef.hostView as EmbeddedViewRef<any>)
.rootNodes[0] as HTMLElement;
if (wrapperClass) {
const hasWrapper = appendTo.querySelector(`.${wrapperClass}`);
if (!hasWrapper) {
const divTag = this.document.createElement('div');
divTag.className = wrapperClass;
appendTo.appendChild(divTag);
}
appendTo = appendTo.querySelector(`.${wrapperClass}`);
}
appendTo.appendChild(domElem);
return componentRef;
}
detachComponent(componentRef: ComponentRef<unknown>): void {
this.appRef.detachView(componentRef.hostView);
componentRef.destroy();
}
}
Secondly, in your component, you just inject the above service and use it.
For example, you want to append AppTestComponent
into <div id="container"></div>
export class AppTestComponent {
name: string;
constructor(
@Inject(MY_TOKEN) public token: any
) {
this.name = token.name;
}
}
export class MyComponent implements OnInit, OnDestroy {
componentRef: ComponentRef<any>;
constructor(
@Inject(DOCUMENT) private document: Document,
private domService: DomService,
){}
ngOnInit() {
this.componentRef = this.domService
.createComponent(
AppTestComponent,
this.document.getElementById('container'),
{name: 'just for test'},
'app-test-container'
);
}
ngOnDestroy(): void {
this.domService.detachComponent(this.componentRef);
}
}