ng-table-virtual-scroll
ng-table-virtual-scroll copied to clipboard
mat-table can not be used inside ngTemplateOutlet
I have a fairly complex table to which I added virtual scroll using this excellent project.
However, as I still want to be able to use my table component without virtual scroll and I do not want to duplicate the whole table component, I tried putting it into an ng-template like this:
<cdk-virtual-scroll-viewport *ngIf="virtualScroll; else tableTemplate" [tvsItemSize]="rowHeight">
<ng-container [ngTemplateOutlet]="tableTemplate"></ng-container>
</cdk-virtual-scroll-viewport>
<ng-template #tableTemplate>
<mat-table>...</mat-table>
</ng-template>
There is an open issue in angular material explaining this behavior. It is stated in the comments that there's a workaround using ContentChildren
instead of ContentChild
. I tried around and was not able to get it to work.
What I ended up doing as a workaround is to subclass your TableItemSizeDirective
and add an input to provide the table manually (because I can easily pick it up as a ViewChild
in my component). This comes with some hacks like manually calling the ngAfterContentInit
again when the input is set and overriding the ngAfterContentInit
to null-check the table. Also, I had to copy your entire Directive
decorator, as this is not inherited. The whole setup will make it hard to update my dependency to your library in the future and I therefor consider it a undesirable solution.
I can't say if there's an easy way to make Angular automatically pick up content children from inside an ngTemplateOutlet
, but an other option would be to accept a reference to a MatTable
as an input to your TableItemSizeDirective
. This would be a small change that allows my usecase to work.
Kind regards and thanks for your work on this great project.
For others struggling with this, my workaround looks like this:
import { VIRTUAL_SCROLL_STRATEGY } from '@angular/cdk/scrolling';
import { AfterContentInit, Directive, Input, forwardRef } from '@angular/core';
import { MatTable } from '@angular/material/table';
import { TableItemSizeDirective, _tableVirtualScrollDirectiveStrategyFactory } from 'ng-table-virtual-scroll';
@Directive({
selector: 'cdk-virtual-scroll-viewport[appItemSize]',
providers: [{
provide: VIRTUAL_SCROLL_STRATEGY,
useFactory: _tableVirtualScrollDirectiveStrategyFactory,
deps: [forwardRef(() => AppTableItemSizeDirective)]
}]
})
export class AppTableItemSizeDirective extends TableItemSizeDirective implements AfterContentInit {
@Input()
set appItemSize(itemSize: string | number) {
this.rowHeight = itemSize;
}
@Input()
set tableComponent(table: MatTable<any>) {
this.table = table;
this.ngAfterContentInit();
}
override ngAfterContentInit() {
if (!!this.table) {
super.ngAfterContentInit();
}
}
}
You saved me thx! Thanks.