Angular嵌套Material表格行展开折叠异常:子行点击干扰外层行的解决
动态嵌套Material表格行展开/折叠异常修复
问题描述
在完全动态的嵌套Material表格中实现行展开折叠功能时,点击子行的展开按钮会触发外层行的展开/折叠状态变更,导致所有子内容联动,无法独立控制各层级的展开状态。
核心问题
当前代码中,子行点击事件直接修改了外层行的element.expanded状态,导致所有依赖该状态的子内容同步变化,没有为嵌套层级维护独立的展开状态。
修复方案
为每个嵌套分组添加独立的expanded属性,修改点击事件和状态绑定逻辑,确保各层级状态互不干扰。
修复后的完整代码
<div class="container"> <table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8"> <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns | async;"> <th mat-header-cell *matHeaderCellDef class="text-Capitalise" [ngClass]=" column== 'subSection'?'noD':'disp' "> {{column && column=='executionId'?'': column && column=='createdBy'?'Created By': column && column=='createdTs'?'Created Date': column && column=='actualsMonth'?'Actual Month': column }} </th> <td mat-cell *matCellDef="let element;" [ngClass]="column== 'title'?'title-col':'disp' && column== 'description'?'description-col':'disp' && column== 'tags'?'tags-col':'disp' && column== 'subSection'?'noD':'disp' "> <span *ngIf="column=='executionId'"> <mat-radio-button color="primary"></mat-radio-button> </span> <span *ngIf="column=='createdTs'"> {{ element.section[column] | date }} </span> <span class="section-head-text" matTooltip="{{element.section[column]}}"> {{ element.section[column] && column=='executionId'?'': element.section[column] && column=='tags'?'': element.section[column]&& column=='createdTs'?'': element.section[column] }} </span> <span class="test-mat-chips" *ngIf="column=='tags'"> <mat-chip-listbox> <span *ngFor="let symbols of element.section.tags"> <mat-chip>{{symbols}} </mat-chip> </span> </mat-chip-listbox> </span> </td> </ng-container> <ng-container matColumnDef="expand"> <th class="expand-column" *matHeaderCellDef aria-label="row actions"> <button mat-icon-button aria-label="expand row" name='toggleButon' (click)="toggle(); $event.stopPropagation()"> <mat-icon *ngIf="!allRowsExpanded">keyboard_arrow_down</mat-icon> <mat-icon *ngIf="allRowsExpanded">keyboard_arrow_up</mat-icon> </button> </th> <td class="expand-column" mat-cell *matCellDef="let element"> <button mat-icon-button aria-label="expand row" (click)="(element.expanded = !element.expanded); $event.stopPropagation()"> <mat-icon *ngIf="!element.expanded">keyboard_arrow_down</mat-icon> <mat-icon *ngIf="element.expanded">keyboard_arrow_up</mat-icon> </button> </td> </ng-container> <ng-container matColumnDef="expandedDetail"> <td class="sub-grid-box" mat-cell *matCellDef="let element" [attr.colspan]="displayedColumnsWithExpand.value.length"> <div *ngFor="let group of element.section.subSection "> <button class="grp-btn" mat-icon-button aria-label="expand row" (click)="(group.expanded = !group.expanded);$event.stopPropagation() "> <mat-icon *ngIf="!group.expanded">keyboard_arrow_down</mat-icon> <mat-icon *ngIf="group.expanded">keyboard_arrow_up</mat-icon> </button> <mat-card class="groupBy collapsible-group"> <mat-card-content> {{group.groupBy.value}} </mat-card-content> </mat-card> <ng-container> <div *ngFor="let insgroup of group.groupBy.subSection" [@detailExpand]="(group.expanded)? 'expanded' : 'collapsed'" [hidden]="!group.expanded"> <span class="collapsible-group-data"> {{insgroup.groupBy.value}}</span> <div> <app-sub-comp [gridData]="insgroup.groupBy.subSection" [displayedColumns]="displayedColumnsWithExpand | async"></app-sub-comp> </div> </div> </ng-container> </div> </td> </ng-container> <ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumnsWithExpand | async"></tr> </ng-container> <tr mat-row *matRowDef="let element; columns: displayedColumnsWithExpand | async; " class="element-row" [class.expanded-row]="element.expanded" (click)="toggleRow(element)"> </tr> <tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="detail-row"></tr> </table> </div>
关键修改说明
- 独立状态维护:将子行点击事件从修改外层
element.expanded改为修改当前分组的group.expanded,每个分组拥有独立的展开状态 - UI逻辑绑定:将展开动画
[@detailExpand]和内容隐藏[hidden]逻辑绑定到group.expanded,确保仅当前分组的内容受影响 - 事件隔离:保留
$event.stopPropagation()防止事件冒泡到外层行,避免误触发外层状态变更
内容的提问来源于stack exchange,提问作者Hitendra Singh Tomar
相关产品推荐
相关产品推荐

