Dynamic ngTemplateOutlet value
Asked Answered
F

3

14

Is there a way to dynamically set the value of the *ngTemplateOutlet directive?

Something along those lines:

<div *ngFor="let item of [ 'div', 'span' ]">
  <ng-container *ngTemplateOutlet="{{ item }}"></ng-container>
</div>

<ng-template #div>
  <div>some text inside a div</div>
</ng-template>

<ng-template #span>
  <span>some text inside a span</span>
</ng-template>

Of course it doesn't work but I guess it explains quite well what I'm trying to achieve: if the item is "div", then it should display the #div template, if it's "span" the #span one.

Felice answered 23/4, 2017 at 23:6 Comment(3)
Remove the double brackets around item and it should work.Trothplight
If I simply remove the brackets it'll display the #item template, which doesn't exist. Meaning it'll display nothing.Felice
Try wrapping item in parenthesis to get it to evaluate as an expression. *ngTemplateOutlet="(item.ref)" If that doesn't work, do let item of [ { ref: 'div' }, { ref: 'span'} ] and use *ngTemplateOutlet="item.ref" Check out this example. #40419098Trothplight
F
19

Just point ngTemplateOutlet at a variable that is a TemplateRef:

In HTML:

<button (click)="toggleTemplateSelected()">Toggle Template</button>
<br />
<p>Showing 
  <span class='viewType' *ngIf="showViewTemplate">C</span>
  <span class='viewType' *ngIf="!showViewTemplate">C2</span> 
  template:</p>
<ng-container *ngTemplateOutlet='liveTemplate'></ng-container>

<!--Templates: -->
<ng-template #tmplC>
  Hello from TemplateC
</ng-template>

<ng-template #tmplC2>
  Hello from TemplateC2
</ng-template>

In code:

@ViewChild('tmplC') tmplC: TemplateRef<any>;
@ViewChild('tmplC2') tmplC2: TemplateRef<any>;

showViewTemplate = true;
liveTemplate: TemplateRef<any>;

toggleTemplateSelected() {
    this.showViewTemplate = !this.showViewTemplate;
    this.liveTemplate = this.showViewTemplate ? this.tmplC : this.tmplC2;
}

You could also point ngTemplateOutlet at a function that returns a TemplateRef.

Flatfish answered 24/11, 2017 at 21:40 Comment(3)
Is there any event emitter exist when TemplateRef change in *ngTemplateOutlet?Neck
Not that I'm aware of, but you could use the function approach that I allude to in the last sentence of my answer and potentially catch the change there.Flatfish
I found the answer to my question here: https://mcmap.net/q/370412/-angular-2-viewchild-returns-undefined Anyway thanks!Neck
D
1

Here is the shortest and best feasible solution

1 Create Directive "dynamic-template.directive.ts"

import { Directive, Input, TemplateRef } from '@angular/core';
@Directive({
  selector: '[dynamic-template]'
})
export class DynamicTemplateDirective {
  @Input() id: number;
  constructor(public template: TemplateRef<any>) { }
}  

2 Define dynamic template in your component helper-content.component.html

<ng-template [dynamic-template] [id]="1">
  This is 1st Template
</ng-template>
<ng-template [dynamic-template] [id]="2">
  This is 2nd Template
</ng-template>
<ng-template [dynamic-template] [id]="3">
  This is 3rd Template
</ng-template>

3 use dynamic template in your component helper-content.component.ts

import { DynamicTemplateDirective } from '@app/components/dynamic-template.directive';

export class HelperContentComponent implements OnInit {
helpTemplate: TemplateRef<any>;
  @ViewChildren(DynamicTemplateDirective) templateRefs: QueryList<DynamicTemplateDirective>;

constructor(private eventService: EventEmitterService) {
  }

getTemplate(templateId: number): TemplateRef<any> {
    return this.templateRefs.toArray().find(x => x.id == templateId).template;
  }

showHelperContent(id: number) {
    
      this.helpTemplate = this.getTemplate(id);
      
     }
}

4 Use helpTemplate variable in helper-content.component.html

<div class="content" >
      <ng-container *ngTemplateOutlet="helpTemplate"></ng-container>
    </div>
Do answered 31/12, 2020 at 12:28 Comment(0)
T
-1

Wrap item in parenthesis to get it to evaluate as an expression. *ngTemplateOutlet="(item.ref)" If that doesn't work, do let item of [ { ref: 'div' }, { ref: 'span'} ] and use *ngTemplateOutlet="item.ref" Similar to Can't get ngTemplateOutlet to work

Trothplight answered 24/4, 2017 at 2:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.