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".
The simplest wrapper around a DOM element is ElementRef . For templates you have TemplateRef that allows you to create an embedded view. Host views can be accessed on componentRef created using ComponentFactoryResolver . The views can be manipulated with ViewContainerRef .
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 .
Embedded views are created from templates using TemplateRef, while host views are created using a view (component) factory. For example, the main component that is used to bootstrap an application ( AppComponent ) is represented internally as a host view attached to the component's host element ( <app-comp> ).
A TemplateRef represents an <ng-template /> . <ng-template let-name let-date="dateNow">{{date}} - Hello {{name}}!</ng-template> An <ng-template /> itself will not do anything at all. We need a ViewContainerRef to insert the template somewhere.
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.
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);
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With