Link

Ng-template

Esta es otra forma de pasar dinamicamente html templates a componentes hijos.

Otra forma mas simple es la que aparece explciada en ng-container revisar y elejir una de las opciones que mas interese.

Empezamos

Con ng-template lo que se quiere hacer es pasar al componente hijo un template html, esto lo que permite es definir un componente hijo con una funcionalidad determinada y ademas añadir un placeholder donde puedes meter un nuevo template sin tener que modificar el componente hijo entero.

Ejemplo de uso

Tengo un componente checkbox que tiene un checkbox normal

<input type="checkbox"

Modificacion que se quiere hacer:

Otro cliente en vez de querer ver los iconos por defecto del checkbox, quiere que salgan unos custom

Tenemos que modificar el componente checkbox y añadir logica solo para ese cliente? NO

Solucion:

html componente padre

<checkbox-component>
  <ng-template CustomCheckboxDirective>
        <img ...>
  </ng-template>
</checkbox-component>

html componente hijo

<ng-container *ngIf="customCheckbox: else customHTMLCheckbox">
  <input type="checkbox">
</ng-container>
<ng-template #customHTMLCheckbox [ngTemplateOutlet]="customCheckboxTemplate">
</ng-template>

ts componente hijo

@ContentChild(CustomCheckboxDirective, { static: true }) customCheckboxTemplate: TemplateRef<any>;

Directiva

import { Directive, TemplateRef } from '@angular/core';
@Directive({
 selector: '[CustomCheckboxDirective]'
})
export class CustomCheckboxDirective {
 constructor(public template: TemplateRef<any>) { }
}

Explicacion del codigo

Lo que se esta haciendo aqui es pasar a traves de la directiva CustomCheckboxDirective un TemplateRef al componente hijo para que lo pinte en el lugar que esta definido

Ejemplo 2 completo

app.component.ts

Componente padre

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

@Component({
  selector: 'my-app',
  template: `
  padre
  <app1>
    <ng-template>
      hijo
    </ng-template>
    <ng-template test>
      hijo2
    </ng-template>
  </app1>
  `,
  styles: [ '' ]
})
export class AppComponent  {
}

app1.component.ts

Componente hijo

 import { Component, Input, ContentChild, TemplateRef, OnInit, AfterViewInit } from '@angular/core';
import { TestDirective } from './directive.directive';

@Component({
  selector: 'app1',
  template: `
  hijo
  <ng-template [ngTemplateOutlet]="testTemplate" >
  </ng-template>
  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class App1Component {
  @ContentChild(TestDirective, { static: true, read: TemplateRef }) testTemplate: TemplateRef<any>;
}

directive.directive.ts

import { Directive, TemplateRef } from '@angular/core';
@Directive({
  selector: '[test]'
})
export class TestDirective {
  constructor(public template: TemplateRef<any>) { }
}

Resultado

image-20200611102504914

Recordatorio:

Acordarse de definir en el decalrations del modulo la directiva