如何自定义mat tree的SelectionModel实现选中节点时禁用互斥节点复选框
Angular Material Tree 节点互斥选择实现方案
前置说明
我们默认你需要互斥的节点A、B可以通过唯一id识别,你可以根据实际业务调整判断条件(比如用name字段识别也可以)。
实现步骤
- 步骤1:定义互斥节点标识集合
在组件类中新增互斥节点配置,替换下面的A的id、B的id为你实际业务中两个互斥节点的id值:
// 新增:互斥节点ID集合 private mutuallyExclusiveIds: Set<string | number> = new Set(['A的id', 'B的id']);
- 步骤2:新增节点禁用状态判断方法
新增方法用于判断指定节点是否需要禁用:
// 新增:判断节点是否禁用 isNodeDisabled(node: ExampleFlatNode): boolean { // 不在互斥组内的节点不禁用 if (!this.mutuallyExclusiveIds.has(node.id)) { return false; } // 已选列表中存在互斥组内的其他节点时,当前节点禁用 return this.checklistSelection.selected.some(selectedNode => this.mutuallyExclusiveIds.has(selectedNode.id) && selectedNode.id !== node.id ); }
- 步骤3:修改节点选择逻辑,选中互斥节点时自动清除同组其他节点的选中状态
分别修改父节点切换方法todoItemSelectionToggle和叶子节点切换方法todoLeafItemSelectionToggle,新增互斥逻辑:
todoItemSelectionToggle(node: ExampleFlatNode): void { this.checklistSelection.toggle(node); const descendants = this.treeControl.getDescendants(node); this.checklistSelection.isSelected(node) ? this.checklistSelection.select(...descendants) : this.checklistSelection.deselect(...descendants); // ========== 新增:互斥逻辑开始 ========== if (this.mutuallyExclusiveIds.has(node.id) && this.checklistSelection.isSelected(node)) { // 找到同组其他已选的互斥节点,取消选中 this.checklistSelection.selected.forEach(selectedNode => { if (this.mutuallyExclusiveIds.has(selectedNode.id) && selectedNode.id !== node.id) { this.checklistSelection.deselect(selectedNode); // 同时取消该节点所有子节点的选中 const otherDescendants = this.treeControl.getDescendants(selectedNode); this.checklistSelection.deselect(...otherDescendants); } }); } // ========== 新增:互斥逻辑结束 ========== descendants.every(child => this.checklistSelection.isSelected(child) ); } todoLeafItemSelectionToggle(node: ExampleFlatNode): void { this.checklistSelection.toggle(node); // ========== 新增:互斥逻辑开始 ========== if (this.mutuallyExclusiveIds.has(node.id) && this.checklistSelection.isSelected(node)) { // 找到同组其他已选的互斥节点,取消选中 this.checklistSelection.selected.forEach(selectedNode => { if (this.mutuallyExclusiveIds.has(selectedNode.id) && selectedNode.id !== node.id) { this.checklistSelection.deselect(selectedNode); // 如果是父节点还要取消子节点选中 const otherDescendants = this.treeControl.getDescendants(selectedNode); this.checklistSelection.deselect(...otherDescendants); } }); } // ========== 新增:互斥逻辑结束 ========== const a=of(this.checklistSelection.selected); }
- 步骤4:修改模板绑定禁用状态
找到你的组件模板中渲染树节点复选框的代码,给mat-checkbox绑定disabled属性:
<mat-checkbox [checked]="checklistSelection.isSelected(node)" [disabled]="isNodeDisabled(node)" <!-- 新增这一行 --> (click)="$event.stopPropagation()" (change)="你原来的选择触发方法,比如todoItemSelectionToggle(node)或者todoLeafItemSelectionToggle(node)" > {{node.name}} </mat-checkbox>
扩展说明
如果需要多组互斥节点,你可以将mutuallyExclusiveIds修改为数组格式,存储多组互斥ID集合,调整判断逻辑即可适配。
内容的提问来源于stack exchange,提问作者MILAD BAHARLO
相关产品推荐
相关产品推荐

