30

I am confused between use cases of createEmbeddedView and createComponent, i.e when to use which one.

Please come up with some cases that can tell about suitable setting to use either of them in "dynamic creation scenario".

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
Blaze
  • 1,642
  • 2
  • 22
  • 20

1 Answers1

66

See this workshop on DOM manipulation or read Working with DOM in Angular: unexpected consequences and optimization techniques where I explain the difference with examples.

These both methods are used to dynamically add content to the component view (DOM). This content can be either a template or a component based. In Angular we usually manipulate the DOM using ViewContainerRef. And both these methods are available on it:

class ViewContainerRef {
    ...
    createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>
    createComponent<C>(componentFactory: ComponentFactory<C>, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>
}

To learn more about manipulating the DOM read Exploring Angular DOM manipulation techniques using ViewContainerRef.

createEmbeddedView

It's used to create a view using TemplateRef. TemplateRef is created by Angular compiler when it encounters ng-template tag in your component html. The view created using this method is called an embedded view.

import { VERSION, Component, ViewChild, TemplateRef, ViewContainerRef } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
      <ng-container #vc></ng-container>
      <ng-template #tpl>
          <h1>Hello, {{name}}</h1>
      </ng-template>
  `,
  styles: ['']
})
export class AppComponent {
  name = `Angular! v${VERSION.full}`;

  @ViewChild('tpl', {read: TemplateRef}) tpl: TemplateRef<any>;
  @ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;

  ngOnInit() {
    this.vc.createEmbeddedView(this.tpl);
  }
}

Stackblitz demo

This approach is used by all structural directives like *ngIf and *ngFor because they are all wrap a ng-template. For example, for *ngIf the code:

<div *ngIf="data">{{name}}</div>

is transformed into

<ng-template ngIf="data">
   <div>{{name}}</div>

And the ngIf directive uses createEmbeddedView internally:

@Directive({selector: '[ngIf]'})
export class NgIf {
    private _updateView() {
       ...
       if (this._thenTemplateRef) {
           this._thenViewRef =
               this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);

createComponent

It's used to create a view using ComponentFactory. It's created by Angular compiler when you specify a component in the bootstrap property of the module and so the compiler generates a factory for it. The view created using this method is called a hostview.

import { Component, ViewContainerRef, ComponentFactoryResolver, NgZone, VERSION, ViewChild } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<h1>Hello Component!</h1>`,
  styles: [``]
})
export class HelloComponent  {}

@Component({
  selector: 'my-app',
  template: `
      <ng-container #vc></ng-container>
  `,
  styles: ['']
})
export class AppComponent {

  @ViewChild('vc', {read:ViewContainerRef}) vc: ViewContainerRef;

  constructor(private resolver: ComponentFactoryResolver) {}

  ngOnInit() {
    const factory = this.resolver.resolveComponentFactory(HelloComponent);
    this.vc.createComponent(factory);
  }
}

Stackblitz demo.

To learn more about the difference between a host view and an embedded view read What is the difference between a view, a host view and an embedded view

Mahesh
  • 3,727
  • 1
  • 39
  • 49
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • Thanks @AngularInDepth.com for your reply. I followed your link to difference between "host view and embedded view" and now my understanding is that embedded views are suited to create dynamic **presentation** view. But, for a smart component, one that can do much more than displaying data, createComponent is the way to go. Am I right on this ? – Blaze Sep 21 '17 at 09:26
  • @Blaze, you're welcome. Well, that's one way to look at it I suppose. Since embedded views are created from `ng-template` and don't have a class associated with them as opposed to components indeed there's not much logic can be put inside `embedded view`. However, I would say that mostly embedded views are used for reusable presentations. All structural directives make use of `ng-template`. I'll add that bit to the answer – Max Koretskyi Sep 21 '17 at 09:36
  • One question, after ViewContainerRef#createComponent is called, can I ensure the component must be in DOM? – Chao Apr 03 '19 at 21:46
  • @Chao, it's in the DOM once the method returns. – Max Koretskyi Apr 10 '19 at 08:12
  • I think angular in depth has changed home since this answer was last updated. @MaxKoretskyi Can you please update the URL to : https://indepth.dev/posts/1134/working-with-dom-in-angular-unexpected-consequences-and-optimization-techniques – Phalgun Mar 23 '21 at 18:19