Tip: This guide assumes you've already read the Essentials Guide. Read that first if you're new to Angular.
In addition to using a component directly in a template, you can also dynamically render components.
There are two main ways to dynamically render a component: in a template with NgComponentOutlet
,
or in your TypeScript code with ViewContainerRef
.
Using NgComponentOutlet
NgComponentOutlet
is a structural directive that dynamically renders a given component in a
template.
@Component({ ... })export class AdminBio { /* ... */ }@Component({ ... })export class StandardBio { /* ... */ }@Component({ ..., template: ` <p>Profile for {{user.name}}</p> <ng-container *ngComponentOutlet="getBioComponent()" /> `})export class CustomDialog { @Input() user: User; getBioComponent() { return this.user.isAdmin ? AdminBio : StandardBio; }}
See the NgComponentOutlet API reference for more information on the directive's capabilities.
Using ViewContainerRef
A view container is a node in Angular's component tree that can contain content. Any component
or directive can inject ViewContainerRef
to get a reference to a view container corresponding to
that component or directive's location in the DOM.
You can use the createComponent
method on ViewContainerRef
to dynamically create and render a
component. When you create a new component with a ViewContainerRef
, Angular appends it into the
DOM as the next sibling of the component or directive that injected the ViewContainerRef
.
@Component({ selector: 'leaf-content', template: ` This is the leaf content `,})export class LeafContent {}@Component({ selector: 'outer-container', template: ` <p>This is the start of the outer container</p> <inner-item /> <p>This is the end of the outer container</p> `,})export class OuterContainer {}@Component({ selector: 'inner-item', template: ` <button (click)="loadContent()">Load content</button> `,})export class InnerItem { constructor(private viewContainer: ViewContainerRef) {} loadContent() { this.viewContainer.createComponent(LeafContent); }}
In the example above, clicking the "Load content" button results in the following DOM structure
<outer-container> <p>This is the start of the outer container</p> <inner-item> <button>Load content</button> </inner-item> <leaf-content>This is the leaf content</leaf-content> <p>This is the end of the outer container</p></outer-container>
Lazy-loading components
You can use both of the approaches described above, NgComponentOutlet
and ViewContainerRef
, to
render components that are lazy-loaded with a standard
JavaScript dynamic import.
@Component({ ..., template: ` <section> <h2>Basic settings</h2> <basic-settings /> </section> <section> <h2>Advanced settings</h2> <button (click)="loadAdvanced()" *ngIf="!advancedSettings"> Load advanced settings </button> <ng-container *ngComponentOutlet="advancedSettings" /> </section> `})export class AdminSettings { advancedSettings: {new(): AdminSettings} | undefined; async loadAdvanced() { this.advancedSettings = await import('path/to/advanced_settings.js'); }}
The example above loads and displays the AdvancedSettings
upon receiving a button click.