You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Materials Tree:实现部分节点互斥单选、部分节点多选

实现Angular Material树组件的混合单选/多选逻辑

针对你的需求,只需在原有全多选树的基础上,通过标记单选组节点和重写选中事件逻辑就能实现部分节点单选、其余多选的效果,具体步骤如下:

1. 扩展节点数据结构,标记单选组

首先给扁平节点(FlatNode)添加标识字段,用来区分哪些节点属于单选组:

// 定义扁平节点接口,新增radioGroup字段标记所属单选组
interface TodoItemFlatNode {
  expandable: boolean;
  name: string;
  level: number;
  radioGroup?: string; // 可选字段,非空则表示该节点属于对应单选组
}

在构建扁平节点的转换方法中,判断节点是否属于Quantity:的子节点,给它们打上单选组标记:

private _transformer = (node: TodoItemNode, level: number) => {
  return {
    expandable: !!node.children && node.children.length > 0,
    name: node.item,
    level: level,
    // 若父节点是Quantity:,则标记该节点属于quantity单选组
    radioGroup: node.parent?.item === 'Quantity:' ? 'quantity' : undefined,
  };
};

2. 重写选中事件处理逻辑

修改原有的选中切换方法,对单选组节点执行互斥选中逻辑,其余节点保持原有多选逻辑:

todoItemSelectionToggle(node: TodoItemFlatNode): void {
  if (node.radioGroup) {
    // 单选组逻辑:先清除同组其他已选中节点
    const selectedInGroup = this.checklistSelection.selected.filter(n => n.radioGroup === node.radioGroup);
    selectedInGroup.forEach(n => this.checklistSelection.deselect(n));
    // 选中当前节点
    this.checklistSelection.toggle(node);
  } else {
    // 原有多选逻辑:切换当前节点选中状态,同步父节点状态
    this.checklistSelection.toggle(node);
    this.checkAllParentsSelection(node);
  }
}

3. 调整父节点选中状态计算(可选)

针对Quantity:这类单选组的父节点,调整其选中状态的判断逻辑,使其符合单选组的行为:

// 判断父节点是否所有子节点都选中(针对单选组父节点特殊处理)
descendantsAllSelected(node: TodoItemFlatNode): boolean {
  const descendants = this.treeControl.getDescendants(node);
  // 若父节点是Quantity:,只要有一个子节点选中即视为"全选"
  if (node.name === 'Quantity:') {
    return descendants.some(child => this.checklistSelection.isSelected(child));
  }
  return descendants.every(child => this.checklistSelection.isSelected(child));
}

// 判断父节点是否部分选中(针对单选组父节点特殊处理)
descendantsPartiallySelected(node: TodoItemFlatNode): boolean {
  const descendants = this.treeControl.getDescendants(node);
  if (node.name === 'Quantity:') {
    // 单选组父节点只有"选中"或"未选中",没有部分选中状态
    return false;
  }
  return descendants.some(child => this.checklistSelection.isSelected(child)) && !this.descendantsAllSelected(node);
}

4. 优化单选组交互体验(可选)

在模板中给单选组节点的复选框添加禁用状态,当同组已有节点选中时,禁用其他节点的复选框,更符合单选交互习惯:

<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
  <li class="mat-tree-node">
    <button mat-icon-button disabled></button>
    <mat-checkbox class="checklist-leaf-node"
                  [checked]="checklistSelection.isSelected(node)"
                  <!-- 同组已有选中节点时,禁用当前节点复选框 -->
                  [disabled]="node.radioGroup && checklistSelection.selected.some(n => n.radioGroup === node.radioGroup && n !== node)"
                  (change)="todoItemSelectionToggle(node)">{{node.name}}</mat-checkbox>
  </li>
</mat-tree-node>

内容的提问来源于stack exchange,提问作者LongestOfJohns

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 13:50:20