16

Angular 5.0.2 Based on the example provided on NgTemplateOutlet https://angular.io/api/common/NgTemplateOutlet

I want to know if there's a way to dynamically create a TemplateRef and then inject it into component's template.

For example let's say a component has the following template

<ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container>
<ng-template #eng let-name><span>Hello {{name}}!</span></ng-template>

component code

class NgTemplateOutletExample {
  myContext = {$implicit: 'World'};
}

What I want is to transform this into a component with the following template

<ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container>

and component code like this

class NgTemplateOutletExample {
  eng:TemplateRef = this.createTemplateRef('<ng-template #eng let-name><span>Hello {{name}}!</span></ng-template>');
  myContext = {$implicit: 'World'};
}

Is it possible to create TemplateRef from a string?

2
  • I think it is possible, maybe not with ngTemplateOutlet though, look for 'Creating components on the fly' in blog.angularindepth.com/… Commented Jul 12, 2018 at 11:32
  • A TemplateRef is a reference to an existing template, you can only get one if the template exists, so there is no way of creating it dynamically. You can though create a component and instantiate that on dynamically without using it anywhere in the html templates directly. Commented Aug 23, 2018 at 13:20

1 Answer 1

6

What you want is to have dynamic templates. So that you can put the template later without changing the same component.

Now how can you achieve this ?

Create the main component renders the template. <main-component>

main.component.html

<div class="box">
  <ng-container [ngTemplateOutlet]="template" [ngTemplateOutletContext]="context"></ng-container>
</div>

main.component.ts

import { Component, OnInit, TemplateRef, ContentChild } from '@angular/core';

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css']
})
export class MainComponent implements OnInit {

  constructor() { }

  @ContentChild("template")
  template :TemplateRef<any>;

  ngOnInit() {

  }

  get context(){
    return this;
  }

}
  • Now you can the same component with different templates*

app.component.html

<app-main>
  <ng-template #template>Content From First Template</ng-template>
</app-main>
<br>
<app-main>
  <ng-template #template>Content From Second Template</ng-template>
</app-main>

Output

enter image description here

Working demo is here https://stackblitz.com/edit/angular-yzkwrq

Sign up to request clarification or add additional context in comments.

1 Comment

Note that passing "this" as context is awful, because this will contain a reference to the template itself, so it basically creates a loop.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.