Instead of a regular way of displaying data to table. I'm trying to create my custom-table component and project the data in the material table via .
like this:
<table mat-table [dataSource]="dataSource">
<!-- I want to Render the header and cell data here -->
<ng-content></ng-content>
<mat-header-row *matHeaderRowDef="headers; sticky: true"></mat-header-row>
<mat-row *matRowDef="let row; columns: headers;"></mat-row>
</table>
So I can call this customized component like this:
<app-customized-table>
<ng-container matColumnDef="id">
<mat-header-cell *matHeaderCellDef> Id </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.Id}} </mat-cell>
</ng-container>
...etc
</app-customized-table>
However, it won't detect the content. Here's a stackblitz example that i'm trying to do.
https://stackblitz.com/edit/angular-qwvcln?file=src%2Fapp%2Fcustom-table.component.ts
Is there a way to do this?
Thanks.
Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you could have a Card component that accepts content provided by another component. With this type of content projection, a component accepts content from a single source.
If you want to style the projected content within <ng-content>, you can do so using :host and ::ng-deep to apply styling to all nested elements within the <contact> component.
By default, the MatTableDataSource sorts with the assumption that the sorted column's name matches the data property name that the column displays. For example, the following column definition is named position , which matches the name of the property displayed in the row cell.
The ng-content is used when we want to insert the content dynamically inside the component that helps to increase component reusability. Using ng-content we can pass content inside the component selector and when angular parses that content that appears at the place of ng-content.
Bit late to the party, but I had the same challenge and was able to solve it as follows:
You can solve it by adding the column definitions to the table programmatically, by using the @ContentChildren
and @ViewChild
functionality:
your template file (e.g. customized-table.component.html
):
<table mat-table [dataSource]="dataSource">
<ng-content></ng-content>
<mat-header-row *matHeaderRowDef="headers; sticky: true"></mat-header-row>
<mat-row *matRowDef="let row; columns: headers;"></mat-row>
</table>
your codebehind (e.g. customized-table.component.ts
):
@Component({
selector: 'app-customized-table',
templateUrl: './customized-table.component.html'
})
export class CustomizedTableComponent<T> implements AfterContentInit {
constructor() { }
@Input() dataSource: T[]; // or whatever type of datasource you have
@Input() headers: string[];
// this is where the magic happens:
@ViewChild(MatTable, { static: true }) table: MatTable<T>;
@ContentChildren(MatColumnDef) columnDefs: QueryList<MatColumnDef>;
// after the <ng-content> has been initialized, the column definitions are available.
// All that's left is to add them to the table ourselves:
ngAfterContentInit() {
this.columnDefs.forEach(columnDef => this.table.addColumnDef(columnDef));
}
}
Now, you're able to use:
<app-customized-table [headers]="headers">
<ng-container matColumnDef="id">
<mat-header-cell *matHeaderCellDef> Id </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.Id}} </mat-cell>
</ng-container>
...etc
</app-customized-table>
Stackblitz working demo with lazy loaded modules
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With