2

I am working on an Angular project and I've made my own table <app-table> component by wrapping an existing table component from the team, let's say <inner-table>, inside it. Please keep in mind that I cannot edit the wrapped table component. I've made changes accordingly, redifining inputs on my wrapper and injecting them back to the <inner-table>.

The existing <inner-table> offers a *customCellTemplate directive that allows us to define templates for the cells of a column. Here's how it is used :

<!-- app.component.html --> 
<inner-table [columns]="columns" ...>
 <ng-container *customCellTemplate="let item; name: 'firstnameTemplate'">
 {{ item.firstname + ' !' }}
 </ng-container>
</inner-table>
// app.component.ts
protected columns = { 
 'firstname': { cell: 'firstnameTemplate', header: 'Firstname' },
 'lastname': { cell: (item) => item.lastname, header: 'Last name' } 
}

This works fine, the firstname column's cells are displaying the firstname followed by a ' !'.

Now the problem

I can't define a <ng-container *customCellTemplate...> tag inside my <app-table> component (the same way I would in my <inner-table>) and project that tag using an <ng-content> inside my <inner-table> in my app-table.component.html. If I understand correctly, the directive will be computed and the inner <inner-table> will not see that directive definition. I've made this example :

This works (column cells are formatted correctly, with a ' !' suffix) :

<!-- app-table.component.html --> 
<div id="app-table-container"> 
 <inner-table [columns]="columns"> 
 <ng-container *customCellTemplate="let item; name: 'firstnameTemplate'"> 
 {{ item.firstname + ' !' }} 
 </ng-container> 
 </inner-table> 
</div>

This does not work (empty column) :

<!-- app.component.html --> 
<app-table [redefinedColumns]="columns"> 
 <ng-container *customCellTemplate="let item; name: 'firstnameTemplate'"> 
 {{ item.firstname + ' !' }} 
 </ng-container> 
</app-table>
<!-- app-table.component.html --> 
<div id="app-table-container"> 
 <inner-table [columns]="redefinedColumns" ...> 
 <ng-content></ng-content> 
 </inner-table>
 Other stuff...
</div>

I can't use the computed ng-template either, this doesn't work :

<!-- app-table.component.html --> 
<div id="app-table-container"> 
 <inner-table [columns]="redefinedColumns" ...> 
 <ng-template customCellTemplate let-item name="firstnameTemplate"> 
 {{ item.firstname + ' !' }} 
 </ng-template> 
 </inner-table> 
</div>

What are my solutions ?

Is there any way I could define a template for a column's cells without having to define them in the wrapped <inner-table> component, as I don't want to end up with an app-table.component.html file being thousands of lines long if I have to define dozens of cell templates. I have thought of making a directive instead of wrapping my <inner-table>, but that would require alot of changes and I don't even know if it can work for some features, it may introduce new problems. Please give me some solid solutions

Thank you !

asked Aug 2, 2025 at 9:37
1
  • Hello! Please provide more information about the customCellTemplate structural directive Commented Aug 3, 2025 at 13:12

1 Answer 1

0
@Directive({
 selector: '[customCellTemplate]'
})
export class CustomCellTemplateDirective {
 @Input() name!: string;
 constructor(public template: TemplateRef<any>) {}
}

app-table.component.ts

import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
import { CustomCellTemplateDirective } from '...'; // path to directive
@Component({
 selector: 'app-table',
 templateUrl: './app-table.component.html'
})
export class AppTableComponent implements AfterContentInit {
 @ContentChildren(CustomCellTemplateDirective)
 customTemplates!: QueryList<CustomCellTemplateDirective>;
 templatesToProject: CustomCellTemplateDirective[] = [];
 ngAfterContentInit(): void {
 // Store them for re-projection
 this.templatesToProject = this.customTemplates.toArray();
 }
}

app-table.component.html

<div id="app-table-container">
 <inner-table [columns]="redefinedColumns">
 <ng-container *ngFor="let tmpl of templatesToProject">
 <ng-template
 [customCellTemplate]
 [name]="tmpl.name"
 [ngTemplateOutlet]="tmpl.template">
 </ng-template>
 </ng-container>
 </inner-table>
</div>
 

app.component.html

<app-table [redefinedColumns]="columns">
 <ng-template customCellTemplate let-item name="firstnameTemplate">
 {{ item.firstname + ' !' }}
 </ng-template>
 <ng-template customCellTemplate let-item name="lastnameTemplate">
 {{ item.lastname.toUpperCase() }}
 </ng-template>
</app-table>
answered Aug 4, 2025 at 23:06
Sign up to request clarification or add additional context in comments.

1 Comment

Code-only answers are discouraged. Please add some explanation.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.