Duplicate the ng-template using ng-content as the body (make a duplicate of ng-content)

I have been working on creating a feature that allows users to add custom columns to a PrimeNg table. The main reason for developing this feature is to provide users with a default table that already has numerous configuration options pre-set.

However, I am facing an issue where I am unable to repeat an ng-template component multiple times.


Version Information

  • Angular version: 7.2.12
  • Primeng version: 7.1.0
  • @angular/animations version: 7.2.12

Goal

My goal is to create a wrapper that simplifies the process of column creation and eliminates the need to create multiple templates within the table body.

For instance, instead of:

<table>
 <!-- Row 1 -->
 <ng-template #header><th>edit></th></ng-template>
 <ng-template #content><button>edit></button></ng-template>

 <!-- Row 2 -->
 <ng-template #header><th>delete></th></ng-template>
 <ng-template #content><button>delete></button></ng-template>
</table>

I aim to simplify it to:

<table>
  <!-- Row 1 -->
  <custom-column>
    <th header>edit></th>
    <button>edit></button>
  </custom-column>

  <!-- Row 2 -->
  <custom-column>
    <th header>delete></th>
    <button>delete></button>
  </custom-column>
</table>

You can find my progress on this in the following StackBlitz link.


Current Issue

Although I have made significant progress, I am currently struggling with repeating the content template for each row in the table. As of now, only the buttons from the last row are showing up. This could be due to the fact that the ng-content transcludes only once.

I would appreciate any guidance on whether achieving my intended functionality is possible and if so, how I should modify my code to make it work correctly.

Answer №1

After encountering limitations with the ng-content component in Angular, which does not support projecting the same content multiple times, I found a solution by injecting templates into the table component instead.

I took inspiration from Primeng's approach to this issue, where they create a directive to hold the template:

@Directive({ selector: '[pTemplate]' })
export class PrimeTemplate {

  @Input() type: string;

  @Input('pTemplate') name: string;

  constructor(public template: TemplateRef<any>) { }

  getType(): string {
    return this.name;
  }
}

Usage:

<ng-template pTemplate="header"></ng-template

This method allows for the creation of reusable templates within the table component, effectively solving the projection problem.


To maintain flexibility without resorting to string comparison (as seen with the 'name' property) and to simplify the retrieval of templates from the querylist, I decided to create 2 directives as an improved implementation:

<ng-container>
  <ng-template appColHeader>Delete</ng-template>
  <ng-template appColContent><button>Not here!</button></ng-template>
</ng-container>

You can find the full implementation of this code on this StackBlitz link.

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

Guide for using two Async Pipe functions in Angular 7

Two different functions are in place to check a specific condition, and the requirement is for both of them to be true simultaneously. How can *ngIf be utilized to achieve this? Currently, setting just one of them works, but the aim is to have both. HTML ...

The elements within the NativeScript components are failing to show the data received from the Django API

My Django API is set up to provide a list of movies titles with their corresponding IDs. I've implemented a movie service in TypeScript that retrieves the list of movie titles and IDs using the GET operation. In my NativeScript project, I have two f ...

What could be the reason my Angular Bearer Token is not showing up in Firefox?

Here is how my function is structured: testFunctionAuth() { const promise = new Promise((resolve, reject) => { this.http.get(AppConfigService.settings.apiServer.rest + 'systems/all', { headers: { 'Authorization': 'B ...

Encountering a type-safety problem while attempting to add data to a table with Drizzle

My database schema is structured like so: export const Organization = pgTable( "Organization", { id: text("id").primaryKey().notNull(), name: text("name").notNull(), createdAt: timestamp("c ...

Oops! Issue encountered while trying to read the file "src/core/database/config.ts"

Need help with migrating a database in a Node Nest.JS application. When running the npx sequelize-cli db:migrate shell command, I encountered the following exception: Error details: Error: TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".t ...

Can Next.js accommodate server-side redirection with internationalization?

I'm working on a small Next.js app that has pages accessible only to logged in users. To manage the authenticated routes, I created an HOC (withAuth) that handles redirection on the server side to prevent page flashing on the client side. Everything i ...

Firestore error: "Unable to retrieve document due to offline client" specifically happening with Cypress tests

While testing my Ionic Angular app with Firebase for logging in, I encountered the following error: "Failed to get document because the client is offline" The app runs smoothly on http://localhost:8100/ and logs in successfully when done manua ...

Exploring the visitor design pattern with numerical enumerated types

I am exploring the use of the visitor pattern to ensure comprehensive handling when adding a new enum value. Here is an example of an enum: export enum ActionItemTypeEnum { AccountManager = 0, Affiliate = 4, } Currently, I have implemented the fol ...

Execute various Office Scripts functions within a single script based on the button that is selected

Imagine you have an Excel spreadsheet with two buttons named populate-current and populate-all. Both buttons execute the same Office Script function that looks something like this: function populateByRowIndex(workbook: ExcelScript.Workbook, rowIndex: numbe ...

The ngOnChanges lifecycle hook does not trigger when the same value is updated repeatedly

Within my appComponent.ts file, I have a property called: this._userMessage Afterwards, I pass it to the childComponent like so: <child-component [p_sUserMessage]='_userMessage'></child-component> In the childComponent.ts file: @ ...

Tips for utilizing ngModel within *ngFor alongside the index?

Currently, I am dynamically generating mat-inputs using *ngFor. My goal is to store each value of [(ngModel)] in a separate array (not the one used in *ngFor) based on the index of the *ngFor elements. Here's my implementation: <div *ngFor="let i ...

Leveraging the TypeScript definitions for express-validator

I've been working on converting my code to TypeScript, but I'm running into issues with express-validator definitions. Here's a snippet of my code: ///<reference path='../../../d.ts/node.d.ts' /> ///<reference path=&apos ...

I've been working on setting up a navbar in React/typescript that links to various routes, but I've hit a snag - every time I try to create a link

import React from 'react' import { Link } from 'react-router-dom' export default function NavBar() { return ( <div className='NavContainer'> <link to='/home'>Home</link> <l ...

Angular tips: Retrieving user ID for API authorization

Within the authorize.service.ts file, there is a service code block that allows me to retrieve the current logged in user's userName: public getUser(): Observable<IUser | null> { return concat( this.userSubject.pipe(take(1), filter( ...

Issue encountered while trying to run `npm install` on an angular-cli

I recently moved my angular-cli project with node modules to a new directory. Upon running npm install, I encountered the following warnings: npm WARN deprecated <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e2838c85978e8 ...

Attempting to modify read-only properties is prohibited in strict mode within the context of [background: url({{XXX}}) no-repeat center center

I encountered an issue in Edge, but everything works fine in Chrome. I can't figure out what's causing the problem... <div class="container-fluid project_img" style="background: url({{_project.images.web}}) no-repeat center center;"> ...

What steps can I take to guarantee that a select change event occurs following the setting of ngmodel in Angular2?

I am facing an issue with a select element wherein a basic (change) handler is attached along with an ngmodel. Whenever an <option> with a ng value is set, the change handler triggers before the [(ngModel)] reflects the new values. <div> ...

Tips for changing the color of an MUI 5 checkbox and label when hovering

I am looking to create a checkbox enclosed in a wrapper with a label. The goal is to change the color of everything inside the wrapper when it is hovered over. Here is an example image: https://i.sstatic.net/T3OU5.png Below is the code I have attempted: ...

Encounter an issue while running the angular build in production mode

Encountering an error stating "Type src/app/createreportcomponent component.ts is part of the declarations of 2 modules" while the normal development build is running smoothly. How can this error be resolved? ****App Module ts file**** import { BrowserMo ...

How can the second subscription's return value be synchronously used in the first subscription in Angular 6?

Currently, I am working on an Angular 6 application and facing a scenario where I have to make multiple API calls in sequence, pass data between them, and then continue the process. For instance, in the .ts file: logout(){ this.apiService.POST({}, "logo ...