How do you hydrate a parent template with child data (Angular 11)

229 views Asked by At

So I have two Angular Components, a parent & a child. I want to do the following:

  1. Define an ng-template in the parent component that references child functions/variables
  2. Pass that template as a parameter to the child component, and
  3. Have the child component display this template using its own instance data.

App.Component (Parent)

import { Component } from "@angular/core";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {}
<reusable-component [customTemplate]="parentTemplate"></reusable-component>

<ng-template #parentTemplate>
  <p>Current color is {{currentColor}}</p>

  <button (click)="changeColorToRed()">
    CHANGE BACKGROUND COLOR TO RED
  </button>

  <button (click)="changeColorToGreen()">
    CHANGE BACKGROUND COLOR TO GREEN
  </button>
</ng-template>

Child Component (reusable-component)

import { Component, Input, OnInit, TemplateRef } from "@angular/core";

@Component({
  selector: "reusable-component",
  templateUrl: "./reusable-component.component.html",
  styleUrls: ["./reusable-component.component.css"]
})
export class ReusableComponentComponent implements OnInit {
  @Input() public customTemplate!: TemplateRef<HTMLElement>;
  currentColor = "white";

  constructor() {}

  ngOnInit() {}

  changeColorToRed() {
    const red = "#FF0000";
    document.body.style.background = red;
    this.currentColor = "red";
  }
  changeColorToGreen() {
    const green = "#00FF00";
    document.body.style.background = green;
    this.currentColor = "green";
  }
}
<ng-container [ngTemplateOutlet]="customTemplate || defaultTemplate">
</ng-container>

<ng-template #defaultTemplate>
  Hello, zuko here!
</ng-template>

How do I provide my parent template with the functions/instance variables from that child Component?

Here's a Stackblitz with the whole project

1

There are 1 answers

3
T. Sunil Rao On BEST ANSWER

Most of the things are fine. For passing data...

Let us first start defining the data to be passed in the Child Component

Child component TS

currentColor = "white";
constructor() {}

ngOnInit() {}

changeColorToRed() {
  const red = "#FF0000";
  document.body.style.background = red;
  this.currentColor = "red";
}
changeColorToGreen() {
  const green = "#00FF00";
  document.body.style.background = green;
  this.currentColor = "green";
}

data = { currentColor: this.currentColor, changeColorToRed: this.changeColorToRed, changeColorToGreen: this.changeColorToGreen };

Now, we pass the context containing the data to the template. Use *ngTemplateOutlet instead of [ngTemplateOutlet] to support chaining

Child component html

<ng-container *ngTemplateOutlet="customTemplate || defaultTemplate; context: data">
</ng-container>

Now, we use the let- attribute to receive the parameters in the parent

Parent component html

<reusable-component [customTemplate]="parentTemplate"></reusable-component>

<ng-template #parentTemplate let-currentColor="currentColor" let-changeColorToRed="changeColorToRed" let-changeColorToGreen="changeColorToGreen">
  <p>Current color is {{currentColor}}</p>

  <button (click)="changeColorToRed()">
    CHANGE BACKGROUND COLOR TO RED
  </button>

  <button (click)="changeColorToGreen()">
    CHANGE BACKGROUND COLOR TO GREEN
  </button>
</ng-template>

Stackblitz