Bug
I define table using dynamic columns like below. In footer cell definition I am using some context object (from current component) and its values.
After context object is updated, table footer displays current data.
<ng-container
*ngFor="let month of months;"
matColumnDef="p{{month}}"
>
<th mat-header-cell *matHeaderCellDef>
{{month}}
</th>
<td
mat-cell
*matCellDef="let element"
>
{{element.someValue}}
</td>
<td mat-footer-cell *matFooterCellDef>
{{someContextObject?.someValue}}
</td>
</ng-container>
After updating context object, table footer does not show changes. It does not work even, if context variable is a simple string.
This works correctly, if table cell is not defined using *ngFor
.
Angular Material 6.4.7
Update - I have been able to make a work around for this using separate ng-template (outside of ng-container), like below. But this is absurd, especially for footer cells, which often show aggregate values (totals) from outside of table data source.
<ng-container
*ngFor="let month of months;"
matColumnDef="p{{month}}"
>
<th mat-header-cell *matHeaderCellDef>
{{month}}
</th>
<td
mat-cell
*matCellDef="let element"
>
{{element.someValue}}
</td>
<td mat-footer-cell *matFooterCellDef>
<ng-container *ngTemplateOutlet="monthFooter;context: {month: month}"></ng-container>
</td>
</ng-container>
<ng-template #monthFooter let-month="month">
{{someContextObject?.someValue}}
</ng-template>
Can you provide a reproduction in StackBlitz. This will help us to investigate the issue you are seeing.
It's interesting - I cannot reproduce it on StackBlitz right now using simple table implementation. I am seeing this in my code, though. I will have to extend StackBlitz example to reproduce the exact conditions I have.
@josephperrott Hi! I'm having what I think may be a similar issue. I was able to reproduce it on stackblitz.
The stackblitz actually includes a few change detection issues.
something
first, and then toggle booly
, the first column doesn't update to represent the change in booly
s value. I think this has to do with the ngIf
ngIf
dngIf
d mat-rows are not updated unless a sort button is pressed (although, this can be worked-around by calling table.renderRows()
- Maybe this is expected?)edit: one more:
Can confirm this is an issue as well. Using @TiS solution with ng-template as a workaround. Issue happens when dataSource is given a whole new data array in ngOnChanges.
ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
if ('data' in changes && !changes['data'].isFirstChange() && this.data) {
this.dataSource.data = [...this.data.report.data];
Further to the issues noted by @literalpie above, I have more workarounds for those interested.
Having noted the 'changed' flags as part of removeHeaderRowDef()
and removeFooterRowDef()
https://github.com/angular/material2/blob/21e646a3e7d99323e3f6d1e2961f416c8695bf48/src/cdk/table/table.ts#L555
https://github.com/angular/material2/blob/21e646a3e7d99323e3f6d1e2961f416c8695bf48/src/cdk/table/table.ts#L567
here are some change detection workarounds for header/footer rows:
ngIf
d --> use table.removeHeaderRowDef(null)
to trigger an update to the header (or table.removeFooterRowDef(null)
)See updated stackblitz - note that toggling booly
refreshes table header and body rows correctly.
Not sure if it is the same root-cause, but I encountered the following problem:
Context:
I have a footer with input fields to add new lines to the table, but only if it is allowed to edit the table values:
<ng-container *ngIf="editable">
<mat-footer-row...>
</mat-footer-row>
</ng-container>
works perfect when I statically set
[editable]="true" or ="false"
but not when I use an @Input() Setter and have a dynamic value like
[editable]="valueReceivedAsyncFromServer"
Workaround:
I'm always rendering the footer but hiding it with css (using ng flexlayout in my case):
<mat-footer-row [fxHide]="!editable" ...>
</mat-footer-row>
not ideal
This issue has grown to include several different issues. It would help us a lot if each issue is opened independently so that we can track them, especially with provided stackblitz reproductions.
Please note that using ng-container around the rows is not our recommended approach to rendering different rows, instead please use the when predicate.
With regards to the first issue, it sounds like it could not be reproduced in stackblitz for us to investigate. If it can, please re-open an issue with a link. Thanks!
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
Further to the issues noted by @literalpie above, I have more workarounds for those interested.
Having noted the 'changed' flags as part of
removeHeaderRowDef()
andremoveFooterRowDef()
https://github.com/angular/material2/blob/21e646a3e7d99323e3f6d1e2961f416c8695bf48/src/cdk/table/table.ts#L555
https://github.com/angular/material2/blob/21e646a3e7d99323e3f6d1e2961f416c8695bf48/src/cdk/table/table.ts#L567
here are some change detection workarounds for header/footer rows:
ngIf
d --> usetable.removeHeaderRowDef(null)
to trigger an update to the header (ortable.removeFooterRowDef(null)
)See updated stackblitz - note that toggling
booly
refreshes table header and body rows correctly.