Skip to main content

Dynamic Components

  • Dynamic Components

  • The function allows creating a ComponentRef instance based on provided Component and a set of options:

import { ApplicationRef, createComponent, EnvironmentInjector } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class ToastService {

constructor(
private appRef: ApplicationRef,
private injector: EnvironmentInjector
) { }

open(text: string) {
// Create a `ComponentRef` instance.
const dialogRef = createComponent(ToastComponent, {
environmentInjector: this.injector
});

dialogRef.setInput('text', text);

document.body.appendChild(dialogRef.location.nativeElement);

// Register the newly created ref using the `ApplicationRef` instance
// to include the component view into change detection cycles.
this.appRef.attachView(dialogRef.hostView);
}
}
export class ToastService {

constructor(
private appRef: ApplicationRef,
private injector: EnvironmentInjector
) { }

open(text: string) {
const newEnvInjector = createEnvironmentInjector([
{
provide: 'MyToken',
useValue: 'Token'
}
], this.injector);

const dialogRef = createComponent(ToastComponent, {
environmentInjector: newEnvInjector
});

dialogRef.setInput('text', text);

document.body.appendChild(dialogRef.location.nativeElement);

this.appRef.attachView(dialogRef.hostView);
}
}
export class ToastService {

constructor(
private appRef: ApplicationRef,
private injector: EnvironmentInjector
) { }

open(text: string) {
const elementInjector = Injector.create({
providers: [
{
provide: 'MyToken',
useValue: 'Token'
}
],
});

const dialogRef = createComponent(ToastComponent, {
environmentInjector: this.injector,
elementInjector
});

dialogRef.setInput('text', text);

document.body.appendChild(dialogRef.location.nativeElement);

this.appRef.attachView(dialogRef.hostView);
}
}
  • The component can be appended to a host element:
export class ToastService {

constructor(
private appRef: ApplicationRef,
private injector: EnvironmentInjector
) { }

open(text: string) {
const dialogRef = createComponent(ToastComponent, {
environmentInjector: this.injector,
hostElement: document.getElementById('toasts-container')!
});

dialogRef.setInput('text', text);

this.appRef.attachView(dialogRef.hostView);
}
}
  • We can pass projectableNodes — A list of DOM nodes that should be projected through of the new component instance:
openDialog<T>(dialogContent: Type<T>) {
const footer = document.createElement('p');
footer.innerText = 'footer';

const dialogContentRef = createComponent(dialogContent, {
environmentInjector: this.injector
})

const dialogRef = createComponent(DialogComponent, {
environmentInjector: this.injector,
hostElement: document.getElementById('dialog-container')!,
projectableNodes: [
// ng-content nodes
[dialogContentRef.location.nativeElement],
// second ng-content (e.g <ng-content select="footer"></ng-content>)
[ footer ]
]
})

this.appRef.attachView(dialogRef.hostView)
}