Angular createEmbeddedView with Context and Injector

By Arvind Rai, May 15, 2023
On this page we will learn to use ViewContainerRef.createEmbeddedView() method in our Angular application. Embedded views are created using <ng-template> and is attached to the container represented by ViewContainerRef using createEmbeddedView() method. We can insert the view in the view container using Component as well as Directive.
The ViewContainerRef represents a container where one or more views can be attached to a component. It has following methods.
1. createEmbeddedView() : Instantiates an embedded view and inserts it into this container.
2. createComponent() : Instantiates a single component and inserts its host view into this container.
3. clear() : Destroys all views in this container.
4. get() : Retrieves a view from this container.
5. insert() : Inserts a view into this container.
6. move() : Moves a view to a new location in this container.
7. indexOf() : Returns the index of a view within the current container.
8. remove() : Destroys a view attached to this container
9. detach() : Detaches a view from this container without destroying it.

On this page we will learn to use createEmbeddedView() method with examples.

ViewContainerRef.createEmbeddedView()

Find the declaration of createEmbeddedView method from Angular doc.
1. With Injector (Introduced in Angular 14)
createEmbeddedView<C>(
            templateRef: TemplateRef<C>, 
            context?: C, 
            options?: { index?: number; injector?: Injector; }
): EmbeddedViewRef<C> 
The createEmbeddedView creates embedded view and inserts into this container that returns the EmbeddedViewRef for newly created view.

Parameters:
The templateRef is the HTML template that defines the view.
The context is the data-binding context of the embedded view as declared in <ng-template>. This is optional.
The options is the object for extra configuration (optional) that includes index and injector as given below.
{ index?: number; injector?: Injector; } 
The index at which the new view is inserted.
The injector is the Injector to be used within the embedded view.

2. Without Injector.
createEmbeddedView<C>(
            templateRef: TemplateRef<C>, 
            context?: C, 
            index?: number
): EmbeddedViewRef<C> 

With Component

In our example we have parent and child component. In parent component we are creating html code using <ng-template>. Within this code we are including child component. We are embeding the <ng-template> code within <div> element that is our view container.
app.component.html
<h3>With Component</h3>
<ng-template #templateRef let-book="bookName" let-writer="writer" let-location>
    <span> I am from {{location}} and like to read {{book}} written by {{writer}} ji. </span>
    <app-student></app-student>
</ng-template>
<div #viewContainerRef> </div> 
app.component.ts
import { Component, ViewChild, Injector, ViewContainerRef, TemplateRef } from "@angular/core";

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html'
})
export class AppComponent {
  @ViewChild('viewContainerRef', { read: ViewContainerRef, static: true })
  viewContainerRef!: ViewContainerRef;

  @ViewChild('templateRef', { read: TemplateRef, static: true })
  templateRef!: TemplateRef;

  allStudents = [
    { name: 'Mohit', age: 25 },
    { name: 'Krishn', age: 30 }
  ];

  ngOnInit() {
    this.viewContainerRef.createEmbeddedView(this.templateRef,
      { bookName: 'Ramayan', writer: 'Valmiki', $implicit: 'Prayag' },
      {
        index: 0,
        injector: Injector.create({
          providers: [{ provide: 'students', useValue: this.allStudents }]
        })
      });
  }
} 
student.component.ts
import { Component, Inject } from "@angular/core";
import { Student } from "./student";

@Component({
    selector: 'app-student',
    template: `
      <div *ngFor="let std of students">
         <p>{{std.name}} - {{std.age}}</p>
      </div>
    `
})
export class StudentComponent {
    constructor(@Inject('students') public students: Student[]) {}
} 
student.ts
export interface Student {
    name?: String;
    age?: number;
} 

With Directive

Find the code to insert the view using Directive.
app.component.html
------
<h3>With Directive</h3>
<ng-container *myDir >
    <app-student></app-student>
</ng-container> 
my.directive.ts
import { Directive, ViewContainerRef, TemplateRef, Injector } from "@angular/core";

@Directive({
  selector: '[myDir]'
})
export class MyDirective {

  constructor(private vcRef: ViewContainerRef, private templateRef: TemplateRef<any>) {
  }
  allStudents = [
    { name: 'Jai', age: 30 },
    { name: 'Arjun', age: 35 }
  ];
  ngOnInit() {
    this.vcRef.createEmbeddedView(this.templateRef, {}, {
      injector: Injector.create({
        providers: [{ provide: 'students', useValue: this.allStudents }]
      })
    })
  }
} 
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { StudentComponent } from './student.component';
import { MyDirective } from './my.directive';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule
  ],
  declarations: [
    AppComponent,
    StudentComponent,
    MyDirective
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { } 
Find the print screen of the output.
Angular createEmbeddedView with Context and Injector

Reference

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us