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

Angular中如何展示formControlName(moduleGroupName)的去重值

Angular 中展示去重后 moduleGroupName 表单值的实现方案

直接遍历 FormArray 全量值渲染的写法,会导致同属一个模块组的每一行都重复显示moduleGroupName,要实现去重展示有两种常用方案,可根据布局需求选择:


方案一:按模块组重构渲染结构(推荐)

核心逻辑是先在TS侧对所有表单项按moduleGroupName分组去重,模板层每个模块组只渲染一次组名输入框,组下挂载对应子模块的权限项,结构清晰易维护。

1. TS侧新增分组去重逻辑

原有BuildFormDynamic方法无需修改,新增一个getter获取去重后的分组数据:

import { FormArray } from '@angular/forms';

// 获取去重后的模块组,关联组内所有表单项的索引
get uniqueModuleGroups() {
  const permissionArray = this.permissionForm.get('permissionForm') as FormArray;
  const groupMap = new Map<string, number[]>();

  permissionArray.controls.forEach((control, index) => {
    const groupName = control.get('moduleGroupName').value;
    if (groupMap.has(groupName)) {
      groupMap.get(groupName).push(index);
    } else {
      groupMap.set(groupName, [index]);
    }
  });

  return Array.from(groupMap.entries()).map(([groupName, itemIndexes]) => ({
    groupName,
    itemIndexes
  }));
}

2. 改造HTML模板

不要直接遍历permissionForm.value(这种写法无法实时响应表单状态更新),改为遍历去重后的分组数据:

<div formArrayName="permissionForm">
  <div *ngFor="let group of uniqueModuleGroups" class="module-group">
    <!-- 每个模块组仅渲染一次moduleGroupName输入框,绑定组内第一个控件即可 -->
    <input 
      type="text" 
      readonly 
      [formControl]="permissionForm.get('permissionForm').at(group.itemIndexes[0]).get('moduleGroupName')"
      class="group-name"
    />
    <!-- 遍历组内所有子权限项,渲染子模块行 -->
    <div *ngFor="let idx of group.itemIndexes" [formGroupName]="idx" class="sub-module-row">
      <!-- 此处保留原有子模块字段,不需要再渲染moduleGroupName -->
      <span>{{ permissionForm.get('permissionForm').at(idx).get('subModules').value }}</span>
      <label><input type="checkbox" formControlName="view" /> 查看</label>
      <label><input type="checkbox" formControlName="add" /> 新增</label>
      <label><input type="checkbox" formControlName="edit" /> 编辑</label>
      <label><input type="checkbox" formControlName="delete" /> 删除</label>
    </div>
  </div>
</div>

提示:因为moduleGroupName是只读属性,绑定组内第一个控件完全可以满足展示需求;如果后续需要支持编辑组名,只需给第一个控件加valueChanges监听,同步修改同组所有项的moduleGroupName值即可保证数据一致。


方案二:轻量改造(不改动原有DOM结构)

如果不想调整现有布局,只是想把重复的组名输入框隐藏,仅保留同组第一个项显示,可以用索引判断的方式实现:

1. TS侧新增判断方法

// 判断当前索引是否为对应moduleGroupName第一次出现的位置
isFirstGroupItem(index: number): boolean {
  const permissionArray = this.permissionForm.get('permissionForm') as FormArray;
  const currentGroup = permissionArray.at(index).get('moduleGroupName').value;
  for (let i = 0; i < index; i++) {
    if (permissionArray.at(i).get('moduleGroupName').value === currentGroup) {
      return false;
    }
  }
  return true;
}

2. 模板加显示判断

<div formArrayName="permissionForm">
  <!-- 注意:遍历controls而非value,保证视图实时同步表单状态 -->
  <div *ngFor="let item of permissionForm.get('permissionForm').controls; let i=index" [formGroupName]="i">
    <!-- 仅同组第一个项显示组名输入框,其余重复项隐藏 -->
    <input type="text" readonly formControlName="moduleGroupName" *ngIf="isFirstGroupItem(i)" />
    <!-- 原有其他控件保持不变 -->
    <input type="checkbox" formControlName="view" />
    <input type="checkbox" formControlName="add" />
    <input type="checkbox" formControlName="edit" />
    <input type="checkbox" formControlName="delete" />
  </div>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:57:13