Understanding ViewContainerRef in Angular

When working with dynamic components in Angular, ViewContainerRef is an essential tool that allows you to programmatically manipulate the DOM and insert components at runtime. This article breaks down how to use @ViewChild with ViewContainerRef, and provides a practical example of rendering a component dynamically.

🔍 What is @ViewChild?

@ViewChild is a decorator that allows you to query a DOM element or Angular directive/component from your template.

Example:

@ViewChild('container', { read: ViewContainerRef, static: true })
container!: ViewContainerRef;

Breakdown:

  • 'container': Refers to a template reference variable, like #container in the HTML.
  • read: ViewContainerRef: Tells Angular to return the ViewContainerRef instead of the default element/component.
  • static: true: Tells Angular to resolve this reference before ngOnInit() (eagerly).

🧱 What is ViewContainerRef?

ViewContainerRef represents a container where you can attach views dynamically. It’s a class provided by Angular that gives you the ability to:

  • Create components at runtime
  • Insert, move, or remove embedded views
  • Interact with the component’s change detection

📦 Dynamic Component Example

1. Host Component

@Component({
  selector: 'app-dynamic-host',
  template: '<ng-template #container></ng-template>',
})
export class DynamicHostComponent implements OnChanges {
  @Input() component!: Type<any>;
  @Input() inputs: Record<string, any> = {};

  @ViewChild('container', { read: ViewContainerRef, static: true })
  container!: ViewContainerRef;

  private componentRef!: ComponentRef<any>;

  ngOnChanges(): void {
    this.loadComponent();
  }

  private loadComponent() {
    this.container.clear();
    this.componentRef = this.container.createComponent(this.component);

    for (const [key, value] of Object.entries(this.inputs)) {
      this.componentRef.setInput?.(key, value);
      if (this.componentRef.instance.hasOwnProperty(key)) {
        this.componentRef.instance[key] = value;
      }
    }

    this.componentRef.changeDetectorRef.detectChanges();
  }
}

2. Dynamic Child Component

@Component({
  selector: 'app-my-dynamic',
  template: '<p>Dynamic component. Test = {{ test }}</p>',
})
export class MyDynamicComponent {
  @Input() test!: number;
}

3. Usage

<app-dynamic-host [component]="myComponent" [inputs]="{ test: 42 }"></app-dynamic-host>

💡 Summary

  • ViewContainerRef is crucial for rendering dynamic content in Angular.
  • You can use @ViewChild to get access to a container for inserting components.
  • This pattern is useful for modals, custom UI builders, dashboards, and plugins.

Dynamic components unlock the full power of Angular’s rendering engine, allowing you to build flexible and powerful interfaces.

Leave a Reply