Skip to content

Commit 6bb61ef

Browse files
committed
Refactor table components to initialize displayedColumns and improve change detection handling
1 parent 906b3b5 commit 6bb61ef

File tree

2 files changed

+72
-23
lines changed

2 files changed

+72
-23
lines changed

src/app/components/usage/copilot/table-workflow-usage/table-copilot-usage.component.ts

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ interface CopilotUsageItem {
2828
})
2929
export class TableCopilotUsageComponent implements OnChanges, AfterViewInit {
3030
columns = [] as UsageColumn[];
31-
displayedColumns = this.columns.map(c => c.columnDef);
31+
displayedColumns: string[] = [];
3232
@Input() data!: CustomUsageReportLine[];
3333
@Input() currency!: string;
3434
dataSource: MatTableDataSource<CopilotUsageItem> = new MatTableDataSource<any>(); // Initialize the dataSource property
@@ -40,9 +40,15 @@ export class TableCopilotUsageComponent implements OnChanges, AfterViewInit {
4040
constructor(
4141
private usageReportService: UsageReportService,
4242
private cdr: ChangeDetectorRef
43-
) { }
43+
) {
44+
this.initializeColumns();
45+
}
4446

4547
ngOnChanges() {
48+
if (!this.data) {
49+
return; // Avoid processing if data is not available yet
50+
}
51+
4652
this.initializeColumns();
4753
let usage: CopilotUsageItem[] = [];
4854
let usageItems: CopilotUsageItem[] = (usage as CopilotUsageItem[]);
@@ -96,21 +102,34 @@ export class TableCopilotUsageComponent implements OnChanges, AfterViewInit {
96102
}
97103
});
98104
});
99-
usage = usageItems
105+
usage = usageItems;
100106

101-
// Update dataSource first
102-
this.dataSource.data = usage;
107+
// Update displayedColumns first
108+
this.displayedColumns = this.columns.map(c => c.columnDef);
103109

104-
// Then update displayedColumns in the next tick to avoid ExpressionChangedAfterItHasBeenCheckedError
105-
setTimeout(() => {
106-
this.displayedColumns = this.columns.map(c => c.columnDef);
107-
this.cdr.detectChanges();
108-
});
110+
// Then update the data source
111+
this.dataSource = new MatTableDataSource<CopilotUsageItem>(usage);
112+
113+
// Apply sort and pagination immediately, without setTimeout
114+
if (this.sort) {
115+
this.dataSource.sort = this.sort;
116+
}
117+
if (this.paginator) {
118+
this.dataSource.paginator = this.paginator;
119+
}
120+
121+
// Mark for check to ensure proper change detection
122+
this.cdr.markForCheck();
109123
}
110124

111125
ngAfterViewInit() {
112-
this.dataSource.paginator = this.paginator;
113-
this.dataSource.sort = this.sort;
126+
// We use next tick to avoid the ExpressionChangedAfterItHasBeenCheckedError
127+
Promise.resolve().then(() => {
128+
if (this.dataSource) {
129+
this.dataSource.paginator = this.paginator;
130+
this.dataSource.sort = this.sort;
131+
}
132+
});
114133
}
115134

116135
applyFilter(event: Event) {
@@ -155,7 +174,15 @@ export class TableCopilotUsageComponent implements OnChanges, AfterViewInit {
155174
});
156175
}
157176
}
177+
178+
// Important: Clear columns before setting new ones
179+
this.columns = [];
180+
181+
// Set new columns
158182
this.columns = columns;
183+
184+
// Update displayedColumns immediately after updating columns
185+
this.displayedColumns = this.columns.map(c => c.columnDef);
159186
}
160187
}
161188

src/app/components/usage/shared-storage/table-shared-storage/table-shared-storage.component.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,25 @@ export class TableSharedStorageComponent implements OnChanges, AfterViewInit {
2929
footer?: () => any;
3030
sticky?: boolean;
3131
}[] = [];
32-
displayedColumns = this.columns.map(c => c.columnDef);
32+
displayedColumns: string[] = [];
3333
@Input() data!: CustomUsageReportLine[];
3434
@Input() currency!: string;
3535
dataSource: MatTableDataSource<SharedStorageUsageItem> = new MatTableDataSource<any>();
3636

3737
@ViewChild(MatPaginator) paginator!: MatPaginator;
3838
@ViewChild(MatSort) sort!: MatSort;
3939

40-
constructor(private cdr: ChangeDetectorRef) {}
40+
constructor(private cdr: ChangeDetectorRef) {
41+
this.initializeColumns();
42+
}
4143

4244
ngOnChanges() {
45+
if (!this.data) {
46+
return; // Avoid processing if data is not available yet
47+
}
48+
4349
this.initializeColumns();
50+
4451
const workflowUsage = this.data.reduce((acc, line) => {
4552
const workflowEntry = acc.find(a => a.repo === line.repositoryName);
4653
const date = line.date;
@@ -94,19 +101,32 @@ export class TableSharedStorageComponent implements OnChanges, AfterViewInit {
94101
});
95102
});
96103

97-
// Update dataSource first
98-
this.dataSource.data = workflowUsage;
104+
// Update displayedColumns first
105+
this.displayedColumns = this.columns.map(c => c.columnDef);
99106

100-
// Then update displayedColumns in the next tick to avoid ExpressionChangedAfterItHasBeenCheckedError
101-
setTimeout(() => {
102-
this.displayedColumns = this.columns.map(c => c.columnDef);
103-
this.cdr.detectChanges();
104-
});
107+
// Then update the data source
108+
this.dataSource = new MatTableDataSource<SharedStorageUsageItem>(workflowUsage);
109+
110+
// Apply sort and pagination immediately, without setTimeout
111+
if (this.sort) {
112+
this.dataSource.sort = this.sort;
113+
}
114+
if (this.paginator) {
115+
this.dataSource.paginator = this.paginator;
116+
}
117+
118+
// Mark for check to ensure proper change detection
119+
this.cdr.markForCheck();
105120
}
106121

107122
ngAfterViewInit() {
108-
this.dataSource.paginator = this.paginator;
109-
this.dataSource.sort = this.sort;
123+
// We use next tick to avoid the ExpressionChangedAfterItHasBeenCheckedError
124+
Promise.resolve().then(() => {
125+
if (this.dataSource) {
126+
this.dataSource.paginator = this.paginator;
127+
this.dataSource.sort = this.sort;
128+
}
129+
});
110130
}
111131

112132
initializeColumns() {
@@ -178,6 +198,8 @@ export class TableSharedStorageComponent implements OnChanges, AfterViewInit {
178198
);
179199
}
180200
this.columns = columns;
201+
// Update displayedColumns immediately after updating columns
202+
this.displayedColumns = this.columns.map(c => c.columnDef);
181203
}
182204

183205
applyFilter(event: Event) {

0 commit comments

Comments
 (0)