I'm submitting a ... (check one with "x")
[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[x] support request => Please do not submit support request here, post on Stackoverflow or Gitter
Current behavior
I'm having a grid.component.ts in my app, which basically wraps the ngx-data-table grid for adding some common behavior which should remain consistent throughout our app.
As such, what I'm also doing is to dynamically generate the columns, based on a column configuration which is being passed to my grid.component.ts like
// app.component.ts
this.gridConfig = {
columns: [
{ prop: 'name', name: 'Name' },
{ prop: 'age', name: 'Age' },
{ prop: 'gender', name: 'Gender', templateRef: this.genderColRef }
]
}
in the template
// app.component.html
<my-grid [data]="rows" [config]="gridConfig" [actionsTemplate]="actions">
</my-grid>
Internally the grid.component (my-grid) passes it along to the ngx-data-table to the grid by dynamically generating the columns:
<ng-container *ngFor="let col of gridConfig.columns">
<ngx-datatable-column *ngIf="!col.templateRef" [prop]="col.prop" [maxWidth]="col.width" [name]="col.name">
...
</ngx-datatable-column>
</ng-container>
Since I'm also allowing to configure a custom ng-template and pass that in as a column, I need to set the column configuration in the afterViewInit event
Expected behavior
The columns should render properly also matching the corresponding widths.
Reproduction of the problem
The problem right now is that the column widths don't correspond with the header column widths. Resizing the browser window (the preview frame in StackBlitz) causes a redraw and fixes the issue.
Here's a demo app which shows the behavior: https://stackblitz.com/edit/angular-ngx-datatable-headerissue
Please tell us about your environment:
Table version: 11.2.0
Angular version: 5.0.0
Browser: all
Language: TypeScript
@marjan-georgiev do you have any idea what could cause this problem? Or maybe there's a better approach for implementing my scenario
@juristr any reason you can't do the assignment in ngOnInit? It seems to be working fine:
https://stackblitz.com/edit/angular-ngx-datatable-headerissue-rcpkp9
Ya, it's beacause I have to reference a ViewChild to grab a ng-template which is just available in the AfterViewInit
to fix this:
Move ng-template before my-grid tag in html file, so will be render before the grid and you can pass it in ngOnInit
Move ng-template before my-grid tag in html file, so will be render before the grid and you can pass it in ngOnInit
@fontsie I see what you mean. I don't think it's related to that. The point is when I want to pass a TemplateRef into the grid configuration based on a ng-template inside my component view. Something like this:
...
@ViewChild('checklistActions') checkListActionsTemplate;
this.configuration = {
columns: [
...
{ prop: 'extra', templateRef: this.checkListActionsTemplate, width: 100 }
]
};
Accessing @ViewChild references is considered to be "safe" just after the ngAfterViewInit lifecycle hook of the component. Before they' might be null. However it turns out it works also in the ngOnInit (at least for the ng-template directives). See below.
@juristr any reason you can't do the assignment in ngOnInit? It seems to be working fine:
馃 Indeed, it seems to work. Normally it's just safe to access @ViewChild in the ngAfterViewInit (see docs). Maybe not for ng-template as they're actually rendered directly inside the same component and not as a child component. Need to dive into this...Anyways, going to leave it like this for now and see if I run into issues.
Thx @marjan-georgiev
create model: Ngx-datatable-resizer.ts
export class NgxDatatableResizer {
name: string;
grow: number;
constructor(name: string, grow: number) {
this.name = name;
this.grow = grow;
}
}
create helper funcion: table-resize2.ts
import {NgxDatatableResizer} from "../../../model/Ngx-datatable-resizer";
/**
* @author: Mateusz Zastawny
*/
export class TableResize2 {
private tableId: string;
private columns: Array<NgxDatatableResizer>;
private columnsMap = {};
private sum: number = 0;
constructor(tableId: string, columns: Array<NgxDatatableResizer>) {
this.tableId = tableId;
this.columns = columns;
this.setMap();
}
private setMap(): void {
this.columns.forEach(column => {
this.columnsMap[column.name] = column.grow;
this.sum = Math.round((this.sum += column.grow) * 100) / 100;
});
}
public width(name: string): number {
const maxWidth = Number(window.getComputedStyle(document.getElementById(this.tableId)).width.slice(0, -2));
return (Math.round((((this.columnsMap[name] * 100) / this.sum) / 100) * 100) / 100) * maxWidth;
}
}
use in .ts component:
//
public tableIdNameResizer: TableResize2 = new TableResize2('tableIdName',
[
new NgxDatatableResizer('name1', 0.3),
new NgxDatatableResizer('name2', 0.4),
new NgxDatatableResizer('name3', 0.87)
]);
//
use in .html component:
<ngx-datatable
id="tableIdName"
[columnMode]="'force'"
>
<ngx-datatable-column [minWidth]="30" [width]="tableIdNameResizer.width('name1')" [canAutoResize]="true" name="NAME1" prop="name1">
<!--..-->
</ngx-datatable-column>
<ngx-datatable-column [minWidth]="30" [width]="tableIdNameResizer.width('name2')" [canAutoResize]="true" name="NAME2" prop="name2">
<!--..-->
</ngx-datatable-column>
<!--..-->
</ngx-datatable>