Reputation: 1
I'm trying to create a reusable table, came about NgTemplateOutlet and it's a nice option, the problem we are facing is that to make the wrapper for the table look clean, we are separating the template into a different "component" and then getting the TemplateRef using ViewContainerRef.createcomponent().instance.TemplateRef, everything works fine except when we try to use the p-table functionality, one case is pSelectbableRow, when setting it up, the table with ngTemplateOutlet stops rendering, it's something that can be overlooked and even be resolved at the template level with css and such but that defeats the purpose of using a css framework and also I'd like to understand Angular at a deeper level as to what is causing it to break and if possible to have an alternate solution or a better solution, thanks in advance.
dynamic.table.component.html
<p-table
[columns]="columns"
selectionMode="single"
[(selection)]="selectedProduct"
dataKey="name"
[value]="data"
>
<ng-template pTemplate="header" let-columns>
<tr>
<th scope="col" class="text-center" *ngFor="let col of columns">
{{ col }}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-columns="columns">
<ng-container
pTemplate="body"
[ngTemplateOutlet]="customBodyTemplate"
[ngTemplateOutletContext]="{
$implicit: rowData,
cols: columns
}"
>
</ng-container>
</ng-template>
</p-table>
dynamic.table.component.ts
@Component({
selector: "app-dynamic-table",
templateUrl: "./dynamic.table.component.html",
styleUrls: ["./dynamic.table.component.scss"]
})
export class DynamicTableComponent {
@Input()
customBodyTemplate!: TemplateRef<any>;
@Input()
data: any[];
columns: any[];
@Output() eventEmit: EventEmitter<any> = new EventEmitter();
selectedProduct: any;
constructor() {}
ngOnInit() {
this.columns = this.toColumns();
}
toColumns() {
const keys = Object.keys(this.data[0]);
return keys.map((column) => {
return column.toUpperCase();
});
}
}
example.component.html
<ng-template #example let-rowData let-columns="cols">
<tr [pSelectableRow]="rowData">
<td class="text-right" *ngFor="let col of columns">
{{rowData[col]}}
</td>
</tr>
</ng-template>
example.component.ts
@Component({
selector: "app-example",
templateUrl: "./example.component.html",
styleUrls: ["./example.component.scss"],
})
export class ExampleComponent {
@ViewChild("example",{ static: true }) public readonly templateRef: TemplateRef<any>;
emit($event: any){
//TODO:Implement action
}
}
We are separating the templates to a different component, the service gets the component and returns the TemplateRef like this example
vcr = inject(ViewContainerRef);
return this.vcr.createComponent(ExampleComponent).instance.templateRef;
I'm assuming it's not working because the pSelectableRow directive is in a different context than the table and as I was writting this I resolved the issue by moving the <tr [pSelectableRow]="rowData> to the dynamic table and only template the "td" and that did the trick, but still I'm posting because I'd still would like to know what was causing this and if my code can be improved.
example.component.html
<ng-template #example let-rowData let-columns="cols">
<td class="text-right" *ngFor="let col of columns">
{{rowData[col]}}
</td>
</ng-template>
Upvotes: 0
Views: 130