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
.
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.
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>
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(): AdvancedSettings} | undefined;
async loadAdvanced() {
const { AdvancedSettings } = await import('path/to/advanced_settings.js');
this.advancedSettings = AdvancedSettings;
}
}
The example above loads and displays the AdvancedSettings
upon receiving a button click.