1

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

Jesper
  • 641
  • 3
  • 11
  • 18
  • The best way to do that would be to follow the [dynamic components](https://angular.io/guide/dynamic-component-loader) guide, which explains how everything works and how to use it. –  Mar 06 '19 at 11:12
  • This seems to be more related to dynamically changing components - Once my component is calling OnInit(), the order of templates are set, so this seems a bit overkill for what the purpose is. I basically need to change 'cars' in `` to be read from the component, And I've seen multiple examples of doing very similar stuff with ViewChild, so I would imagine it should be doable with this approach, I just haven't figured it out yet – Jesper Mar 06 '19 at 12:22
  • Well in case you haven't seen it, you ARE dynamically changing components. But suit yourself, I'm not the one having the issue. Good luck with it ! –  Mar 06 '19 at 12:42
  • 1
    Maybe I didn't explain myself good enough, but if you look at the suggested answer from @taras-d, that is more in lines of what I was thinking – Jesper Mar 06 '19 at 12:47

1 Answers1

5

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>
taras-d
  • 1,789
  • 1
  • 12
  • 29