Skip to content

Latest commit

 

History

History
129 lines (106 loc) · 3.58 KB

programmatic-rendering.en.md

File metadata and controls

129 lines (106 loc) · 3.58 KB

Programmatically rendering components

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 createComponentmethod 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(): 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.