Using Angular: Incorporating multiple components into a ng-container ngTemplateOutlet

In my project, I have constructed a wrapper component named wrapperComponent:

export class Wrappercomponent {
  @ContentChild(TemplateRef) detailRef;

  toggleComponents: boolean = false;
  constructor() {}
  toggle() {
    this.toggleComponents = !this.toggleComponents;
  }
}

Additionally, I have this specific template html:

<div *ngIf="toggleComponents; else plugintemplate">
  <ng-container *ngTemplateOutlet="detailRef"></ng-container>
</div>
<ng-template #plugintemplate></ng-template>
<button (click)="toggle()">Toggle</button>

My goal is to be able to toggle between two components residing inside my wrapper component (my-component-1 and my-component-2):

<wrapper-component>
  <ng-template #detailRef>
    <my-component-1></my-component-1>
  </ng-template>
  <my-component-2></my-component-2>
<wrapper-component>

However, based on my current logic, only the component inserted into templateRef detailRef is visible, while the other one (my-component-2) remains hidden. How can I successfully insert both components into separate containers?

Answer №1

Choosing the initial TemplateRef is quite straightforward:

@ContentChild(TemplateRef) detailRef;

If you want to differentiate between templates, assign unique identifiers like this:

<wrapper-component>
  <ng-template #detailRef>
    <my-component-1></my-component-1>
  </ng-template>
  <ng-template #pluginRef>
    <my-component-2></my-component-2>
  </ng-template>
</wrapper-component>

To access them using strings:

export class WrapperComponent {
  @ContentChild("detailRef") detailRef;
  @ContentChild("pluginRef") pluginRef;
  toggleComponents: boolean = false;

  toggle() {
    this.toggleComponents = !this.toggleComponents;
  }
}

A simple ternary operation can switch between them:

<ng-container *ngTemplateOutlet="toggleComponents ? detailRef : pluginRef"></ng-container>
<button (click)="toggle()">Toggle</button>

Try it on Stackblitz: https://stackblitz.com/edit/angular-ivy-vyuv3x?file=src/app/wrapper/wrapper.component.ts

Explore ContentChild documentation: https://angular.io/api/core/ContentChild


An alternative method is using @ContentChildren(TemplateRef) to gather all inner templates without identifiers. Here's a way to cycle through them:

<wrapper-component>
  <ng-template>
    <my-component-1></my-component-1>
  </ng-template>
  <ng-template>
    <my-component-2></my-component-2>
  </ng-template>
  <ng-template>
    <my-component-3></my-component-3>
  </ng-template>
</wrapper-component>
export class WrapperComponent {
  @ContentChildren(TemplateRef) templates: QueryList<TemplateRef<any>>;
  index = 0;

  get currentTemplate() {
    return this.templates.get(this.index);
  }

  cycle() {
    this.index = (this.index + 1) % this.templates.length;
  }
}
<ng-container *ngTemplateOutlet="currentTemplate"></ng-container>
<button (click)="cycle()">Cycle</button>

Experience it live on Stackblitz: https://stackblitz.com/edit/angular-ivy-rzyn64?file=src/app/wrapper/wrapper.component.ts

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to incorporate NPM packages into your browser projects using TypeScript

This is the current setup: index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8> <script src="../node_modules/systemjs/dist/system.js"></script> <script src="../node_modules/lodash/in ...

Checking React props in WebStorm using type definitions

Currently, I am utilizing WebStorm 2018.3.4 and attempting to discover how to conduct type checking on the props of a React component. Specifically, when a prop is designated as a string but is given a number, I would like WebStorm to display an error. To ...

Collection of personalized forms where the parent is a FormGroup

One scenario I'm working on involves creating multiple custom formgroup classes that have FormGroup as their parent class, structured like this: export class CustomFormGroup1 extends FormGroup { //custom properties for this FormGroup const ...

Leveraging NGRX in an Angular Library

Incorporating NGRX into my application has been a seamless process. However, I encountered a challenge in my Angular Library where I needed to integrate that same NGRX module and build upon it. Unfortunately, I faced an issue when attempting to invoke Stor ...

Organizing validators within reactive forms in Angular

When creating a form in Angular, I have multiple fields that need validation. Below is the code I am using to create the form: requestForm = this.formBuilder.group({ requestorName: ['', [Validators.required]], requestorEmail: ['&apo ...

Create a unique type in Typescript that represents a file name with its corresponding extension

Is there a way for me to specify the type of a filename field in my object? The file name will consist of a string representing the name of the uploaded file along with its extension. For instance: { icon: "my_icon.svg" } I am looking for a ...

Ionic datetime returns default values upon initialization

I'm currently in the process of developing an Ionic-Angular-app. I require a datetime component on a page to set the creation date of an object. I am using formGroup for this purpose, but whenever I choose a different date, it always reverts back to t ...

Create a collection of values and assign it to a form control in Ionic 2

How can I set default values for ion-select with multiple choices using a reactive form in Angular? FormA:FormGroup; this.FormA = this.formBuilder.group({ toppings:['',validators.required] }); <form [formGroup]="FormA"> <i ...

What is the best way to incorporate a 'category filter' in Angular2?

Unique Scenario In my Angular2 application, I have implemented code in a component's view parent.component.html that iterates through an array of items and generates a new component for each item: <div class="list-items"> <!-- The colored ...

Creating a responsive and engaging user interface can be achieved by adding animation effects to

I am currently utilizing Ionic 2+ and attempting to add animation to an image using animate.css. Upon initial loading, the image should display a rubberBand animation, and with each click, it should switch to a bounce animation. The rubberBand animation wo ...

Utilize ngx-translate with an array as interpolation values

When working with ngx-translate, I use the instant method to translate messages into the user's language. These messages are provided as JSON objects and some of them contain dynamic values: { "message.key": "First value is {{0}} and se ...

Angular Project: Exploring Classes and Interfaces with and without the Export Keyword

Currently, I am delving into the world of Angular. I have taken up a video course and also referred to a PDF book, but I find myself perplexed when it comes to understanding the usage of the "export" keyword... The PDF course focuses on Angular 5 and util ...

Obtain the name of a node using its identification number in D3JS

I am currently working on implementing a generalized tooltip feature. This tooltip will display the name and other relevant data of the active node. For example, if node 3 is currently active, the tooltip will show the name and distance (not link distance) ...

Unleashing the power of RXJS: Leveraging IntervalObservable coupled with the

I recently incorporated HTTP pooling into my Angular application using IntervalObservable and startWith for immediate activation. I'm curious to know if IntervalObservable waits for the initial/previous call to finish streaming data. Also, is there a ...

An unhandled promise rejection occurred because no routes could be found to match. URL Segment:

I'm facing an issue with my application where it doesn't recognize the route even though I have defined and imported it in app.module. Whenever I try to redirect to a specific route upon data retrieval, I encounter this exception: onSubmit(){ ...

The NGRX + Resolver issue arises when the component loads before the action is fully dispatched, causing interaction problems

I'm currently facing an issue with fetching data from a route and loading it into my state before displaying my detail component. To tackle this, I've implemented a resolver. Although my get request seems to be functioning, it appears that the AP ...

TypeScript does not evaluate the boolean left operand when using the && operator

While working with TypeScript, I encountered a scenario similar to the code snippet below: const getString = (string: string) => string // No errors getString("foo"); // Argument of type 'boolean' is not assignable to parameter of ...

Utilizing the MapToIterable Angular Pipe with TypeScript

Exploring the implementation of a pipe in Angular. Discovered that ngFor doesn't work with maps, prompting further research to find a solution. It seems that future features may address this issue, but for now, utilizing a mapToIterable pipe is the re ...

Every time I attempt to submit the login form on the Ionic and Angular page, instead of capturing the values of the form group, the page simply refreshes

Struggling with submitting the login form in Ionic and Angular? When attempting to submit, the page reloads instead of capturing the form group values. I am utilizing angular reactive forms and form builder within the ionic framework. Need assistance in id ...

Using TypeScript for Context Providers

I successfully implemented a basic context provider using ES6, but I am struggling to adapt it for use in a TypeScript project. Each resource I find online offers a different perspective on how to integrate the context api. My issue revolves around workin ...