Igx-Tree-Grid状态持久化:设置状态后单元格无法展开问题
IgxTreeGrid状态持久化后单元格展开失效问题
我在给应用添加状态持久化功能时,遇到IgxTreeGrid调用setState后单元格未按预期展开的问题。原本以为setState会自动处理树形行的展开状态,但完全没效果;尝试手动调用expandRow方法时,还触发了以下错误:
TypeError: Cannot read properties of undefined (reading 'expanded') at _IgxTreeGridAPIService.allow_expansion_state_change (infragistics-igniteui-angular.mjs:111010:13)
已确认状态数据已正确存储选中行和展开行信息:
- 单元格选择信息:
"cellSelection": [{ "rowStart": 8, "rowEnd": 8, "columnStart": 0, "columnEnd": 0 }]
- 展开信息:
"expansion": [[{ "code": 20, "description": "STEELWORK", "libraryId": "aff67ced-12aa-4b7b-a3af-08db8f460e7f", "jointDisciplineId": null, "schedules": [...] }]]
组件代码
<igx-tree-grid igxGridState #disciplineSchedulesGrid (columnInit)="onDisciplineScheduleColumnInit($event)" [data]="disciplineList" [isLoading]="!disciplineList" [autoGenerate]="false" [allowFiltering]="true" [emptyGridTemplate]="emptyGrid" childDataKey="schedules" expansionDepth="0" [rowSelection]="'single'" [hideRowSelectors]="true" (rowSelectionChanging)="selectScheduleGridRow($event)"> <igx-grid-toolbar> <igx-grid-toolbar-title>Rate Review</igx-grid-toolbar-title> <div *ngIf="bidderRates" style="display:flex"> <igx-select #select name="bidderSelect" [placeholder]="'Please select Bidder'" (selectionChanging)="selectBidderId($event)" id="bidderSelect" class="vertical-centre"> <igx-select-item *ngIf="!bidderList" [value]="null"> No Bidders created </igx-select-item> <igx-select-item *ngFor="let bidder of bidderList" [value]="bidder.id"> {{ bidder.bidderId }} <span *ngIf="bidder.name"> - {{ bidder.name }}</span> </igx-select-item> </igx-select> </div> <button type="button" id="btnAdd" igxButton="contained" igxRipple igxRippleCentered="true" (click)="gridStateComponent.showAddDialog(gridId, rateGridState)">Add State</button> <igx-select *ngIf="gridStateComponent" #select name="gridSelect" [(ngModel)]="gridStateComponent.selectedGridStateId" (selectionChanging)="gridStateComponent.selectGridStates($event)" id="gridSelect" class="vertical-centre" style="padding-left: 0;"> <igx-select-item [value]="'default'" (click)="restoreGrid()"> DEFAULT </igx-select-item> <igx-select-item *ngFor="let gridState of gridStateComponent.filteredGridStates" [value]="gridState.id"> {{ gridState.stateName }} </igx-select-item> </igx-select> <button *ngIf="canDownload" #btnDownload id="btnDownload" igxButton="contained" igxRipple igxRippleCentered="true" (click)="startExcelDownload()" [disabled]="downloadRunning || (bidderRates && !bidderId)"> <igx-icon name="download" style="padding-right: 1rem;"></igx-icon>Download Rates </button> </igx-grid-toolbar> <igx-column field="id" header="id" [editable]="false" [sortable]="false" [groupable]="false" [filterable]="false" [resizable]="true" [hidden]="true"></igx-column> <igx-column field="code" header="Disciplines & Schedules" [sortable]="true" [filterable]="true" [resizable]="true"> <ng-template #disciplineScheduleCodeTemplate igxCell let-cell="cell"> <span class="igx-grid__td" style="width: 100%">{{ cell.value | SORCode: disciplineCodeFormat }} - {{ cell.row.data.description }}</span> </ng-template> </igx-column> </igx-tree-grid>
状态选择方法代码
selectGridStates(event: ISelectionEventArgs) { if (event.newSelection.value === "default") { this.selectedGridStateId = 'default'; return; } this.selectedGridStateId = this.gridStates.filter(gs => gs.id == event.newSelection.value)[0].id; const stateName = this.filteredGridStates.filter(gs => gs.id === this.selectedGridStateId)[0].stateName; this.gridIds.forEach(gridId => { const state = this.gridStates.filter(gs => gs.gridId === gridId && gs.stateName === stateName)[0].state; this.gridStateDirectives[gridId].setState(JSON.parse(state)); this.cdr.detectChanges(); // Manually apply cell expansion state const expansionState = JSON.parse(state).expansion; if (expansionState) { expansionState.forEach(exp => { if (exp[1]) { const row = this.gridStateDirectives[gridId]?.grid?._dataView?.find( r => r.key?.id === exp[0].id); row.expanded = true; this.gridStateDirectives[gridId].grid.expandRow(row.id); } }); } }); }
问题原因与修复方案
1. 状态存储格式错误
当前存储的expansion是完整行对象的嵌套数组,TreeGrid无法直接匹配这些数据来定位行。应该只存储行的唯一标识(比如libraryId或id),修改存储格式为:
"expansion": ["aff67ced-12aa-4b7b-a3af-08db8f460e7f"]
或者键值对格式(记录是否展开):
"expansion": {"aff67ced-12aa-4b7b-a3af-08db8f460e7f": true}
2. 手动展开时的行获取方式错误
不要直接操作内部属性_dataView,改用TreeGrid提供的getRowByKey方法获取行实例,同时延迟执行展开操作确保数据视图已更新:
selectGridStates(event: ISelectionEventArgs) { if (event.newSelection.value === "default") { this.selectedGridStateId = 'default'; return; } // 简化查找逻辑,避免多次filter const targetState = this.gridStates.find(gs => gs.id === event.newSelection.value); if (!targetState) return; this.selectedGridStateId = targetState.id; const stateName = targetState.stateName; this.gridIds.forEach(gridId => { const gridState = this.gridStates.find(gs => gs.gridId === gridId && gs.stateName === stateName); if (!gridState) return; const parsedState = JSON.parse(gridState.state); this.gridStateDirectives[gridId].setState(parsedState); // 延迟执行,确保setState完成后数据视图稳定 setTimeout(() => { const expansionState = parsedState.expansion; if (expansionState) { // 针对ID数组格式处理 expansionState.forEach(rowKey => { const row = this.gridStateDirectives[gridId].grid.getRowByKey(rowKey); if (row) { this.gridStateDirectives[gridId].grid.expandRow(row.key); } }); // 如果是键值对格式,替换为以下代码: // Object.entries(expansionState).forEach(([rowKey, isExpanded]) => { // if (isExpanded) { // const row = this.gridStateDirectives[gridId].grid.getRowByKey(rowKey); // if (row) this.gridStateDirectives[gridId].grid.expandRow(row.key); // } // }); } this.cdr.detectChanges(); }, 0); }); }
3. 确保igxGridState包含展开状态配置
在模板中明确指定igxGridState要包含的状态键,确保expansion被纳入持久化范围:
<igx-tree-grid igxGridState="{ include: ['expansion', 'cellSelection', 'sorting', 'filtering'] }" #disciplineSchedulesGrid <!-- 其他属性保持不变 --> >
内容的提问来源于stack exchange,提问作者lross33
相关产品推荐
相关产品推荐

