Jesper
Jesper

Reputation: 747

Angular dynamically display templates with *ngTemplateOutlet, based on component variable

Let me start by saying that I did look at several other questions regarding ngTemplateOutlet (like: Angular 2 dynamically change the template in the ngTemplateOutlet or ngTemplateOutlet with dynamic value), but they didn't really cover what I'm trying to do, or maybe I can't see how the logic can be applied to what I'm trying to achieve.

My goal:

I have a page, where I want to be able to change the order of my templates being displayed.

I have 2 simple templates, "colors" and "fonts":

<ng-template #colors>
  Red: #FF0000
  Green: #00FF00
  Blue: #0000FF
</ng-template>

<ng-template #fonts>
  Helvetica
  Verdana
  Times New Roman
</ng-template>

I have no problem showing these in a predefined order:

<div>
  <ng-container *ngTemplateOutlet="colors"></ng-container>
</div>
<div>
  <ng-container *ngTemplateOutlet="fonts"></ng-container>
</div>

My problem is, I don't know how to display these templates based on a variable on my component. My component holds an array variable, which contains the order and names of the templates I want to display:

public order: ['fonts', 'colors'];

Notice here, that the order of the templates are switched, so "fonts" should be shown first, then "colors".

My idea was to assign the *ngTemplateOutlet value based on the order variable like this:

<ng-container [ngTemplateOutlet]="order[0]"></ng-container>
<ng-container [ngTemplateOutlet]="order[1]"></ng-container>

But when I do so, I get the following console error:

TypeError: templateRef.createEmbeddedView is not a function

I'm not exactly sure where I'm going wrong with this, or how I can get the *ngTemplateOutlet to take it's template name from an array variable on my component.

I created this stackblitz for it: https://stackblitz.com/edit/angular-q7uqbx

Any help would be much appreciated!

Kind regards,

Jesper

Upvotes: 1

Views: 4167

Answers (1)

taras-d
taras-d

Reputation: 1827

You need to use ViewChild to get reference to the templates and store templates in the array.

Component:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('colors') colors: TemplateRef<any>;
  @ViewChild('fonts') fonts: TemplateRef<any>;

  public order = [];

  ngAfterViewInit(): void {
    this.order = [this.fonts, this.colors];
  }
}

Template:

<ng-template #colors>
  Red: #FF0000
  Green: #00FF00
  Blue: #0000FF
</ng-template>

<ng-template #fonts>
  Helvetica
  Verdana
  Times New Roman
</ng-template>

<ng-container [ngTemplateOutlet]="order[0]"></ng-container>
<ng-container [ngTemplateOutlet]="order[1]"></ng-container>

Upvotes: 5

Related Questions