问题
I've a angular material table which uses detailRow directive to insert a detail/sibling adjacent row to a table row.
StackBlitz
I wanted to give it an appearance of as if the row is being expanded or collapsed, so I added couple of icons to it which are toggled on the click of cell containing them.
<mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
<mat-cell *matCellDef="let element">
<button mat-icon-button color="primary" (click)="element[i] = !element[i]">
<mat-icon id="expand_more" #expand_more *ngIf="!element[i] " >expand_more</mat-icon>
<mat-icon id="expand_less" #expand_less *ngIf="element[i] ">expand_less</mat-icon>
</button>
</mat-cell>
However if the I leave the row expanded and paginate or do a sort the icons do not toggle because there's no way for them to be toggled.
I've tried hooking into the page
event or the sortChange
event but came up empty.
I'm aware that there's new way to do expand/collapse in angular material v7 which probably works well with pagination and sort but its gonna be a while before I upgrade, in the mean time does anyone have any ideas on how to solve this.
回答1:
Short Answer
In cdk-detail-row.directive.ts add this
ngOnDestroy(): void {
this.row[undefined] = false;
}
Long Answer
Firstly, You are capturing click in 2 places once in mat-row and the other in mat-cell(Clicking on the icon triggers both events. Clicking anywhere else on the row only triggers onToggleChange). And also this element[i] = !element[i]
is a hack - (variable i
is undefined). So if you click anywhere else in the row the expand icon does not change this is why I got confused as I thought it is not suppose to change. The example will just take out the click on mat-cell to make it simple.
In table-basic-example.html you should remove the (click) output from it and add the row argument to the method onToggleChange($event, row). And change the *ng-if to listen to element.close instead
<ng-container matColumnDef="expandCollapse">
<mat-header-cell *matHeaderCellDef> Action </mat-header-cell>
<mat-cell *matCellDef="let element">
<button mat-icon-button color="primary">
<mat-icon id="expand_more" #expand_more *ngIf="!element.close" >expand_more</mat-icon>
<mat-icon id="expand_less" #expand_less *ngIf="element.close">expand_less</mat-icon>
</button>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"
class="element-row"
[cdkDetailRow]="row" [cdkDetailRowTpl]="tpl"
(toggleChange)="onToggleChange($event, row)">
</mat-row>
table-basic-example.ts
Add the close property to interface element
export interface Element {
name: string;
position: number;
weight: number;
symbol: string;
close?: boolean;
}
Now we will handle the close and open of the row in the method onToggleChange.
onToggleChange(cdkDetailRow: CdkDetailRowDirective, row: Element): void {
if (this.singleChildRowDetail && this.openedRow && this.openedRow.expended) {
this.openedRow.toggle();
}
if (!row.close) {
row.close = true;
} else {
row.close = false;
}
this.openedRow = cdkDetailRow.expended ? cdkDetailRow : undefined;
}
Lastly, In cdk-detail-row.directive.ts we will want to close the row once the directive is destroyed by pagination or toggling away. So we will implement the onDestroy method
export class CdkDetailRowDirective implements OnDestroy{
...Details of implementation.....
}
The new ngOnDestroy method should look like this
ngOnDestroy(): void {
this.row.close = false;
}
来源:https://stackoverflow.com/questions/53775715/mattable-expand-collapse-icon-issue-on-pagination-and-sort