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 !
-
Hello! Please provide more information about the customCellTemplate structural directivefixAR496– fixAR4962025年08月03日 13:12:38 +00:00Commented Aug 3, 2025 at 13:12
1 Answer 1
@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>
1 Comment
Explore related questions
See similar questions with these tags.