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

基于动态JSON在Angular中实现带全选的分组复选框响应式表单

Angular 响应式分组复选框(带组内全选/全局全选)

1. 模块配置

先在功能模块中导入响应式表单依赖:

import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { CheckboxGroupComponent } from './checkbox-group.component';

@NgModule({
  declarations: [CheckboxGroupComponent],
  imports: [ReactiveFormsModule]
})
export class YourFeatureModule { }

2. 组件逻辑

在组件类中处理表单构建、全选状态同步逻辑:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms';

@Component({
  selector: 'app-checkbox-group',
  templateUrl: './checkbox-group.component.html',
  styleUrls: ['./checkbox-group.component.css']
})
export class CheckboxGroupComponent implements OnInit {
  // 传入的动态分组数据
  groupData = [
    {
      "label": "General",
      "data": [
        { "title": "parameters.deviceInfo.name" },
        { "title": "assetAttributes.manufacturerLabel" }
      ]
    },
    {
      "label": "Associated Device",
      "data": [
        { "title": "assetAttributes.operationsLabel" },
        { "title": "assetAttributes.adapterIpAddress" }
      ]
    },
    {
      "label": "profile.identificationTabLabel",
      "data": [
        { "title": "assetAttributes.assetIdLabel" }
      ]
    },
    {
      "label": "profile.communicationTabLabel",
      "data": [
        { "title": "profile.networkGroupLabel" },
        { "title": "assetAttributes.gtwAddressLabel" }
      ]
    },
    {
      "label": "profile.locationTabLabel",
      "data": [
        { "title": "assetAttributes.latitudeLabel" },
        { "title": "assetAttributes.longitudeLabel" }
      ]
    },
    {
      "label": "profile.customersTabLabel",
      "data": [
        { "title": "assetAttributes.mRidLabel" },
        { "title": "assetAttributes.epsNameLabel" }
      ]
    }
  ];

  mainForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit(): void {
    this.buildForm();
  }

  // 构建响应式表单结构
  buildForm(): void {
    const groupControls = this.groupData.map(group => {
      return this.fb.group({
        groupSelect: new FormControl(false),
        items: this.fb.array(
          group.data.map(() => new FormControl(false))
        )
      });
    });

    this.mainForm = this.fb.group({
      groups: this.fb.array(groupControls)
    });
  }

  // 获取所有分组的FormArray
  get groups(): FormArray {
    return this.mainForm.get('groups') as FormArray;
  }

  // 获取指定分组的选项FormArray
  getGroupItems(groupIndex: number): FormArray {
    return this.groups.at(groupIndex).get('items') as FormArray;
  }

  // 切换组内全选状态
  toggleGroupSelect(groupIndex: number): void {
    const group = this.groups.at(groupIndex);
    const isSelected = group.get('groupSelect').value;
    const items = this.getGroupItems(groupIndex);

    items.controls.forEach(control => control.setValue(isSelected));
  }

  // 组内单个选项变化时,同步组全选状态
  onItemChange(groupIndex: number): void {
    const items = this.getGroupItems(groupIndex);
    const allSelected = items.controls.every(control => control.value);
    this.groups.at(groupIndex).get('groupSelect').setValue(allSelected);
  }

  // 全局全选所有选项
  selectAll(): void {
    this.groups.controls.forEach((_, index) => {
      this.groups.at(index).get('groupSelect').setValue(true);
      this.toggleGroupSelect(index);
    });
  }

  // 全局取消全选所有选项
  deselectAll(): void {
    this.groups.controls.forEach((_, index) => {
      this.groups.at(index).get('groupSelect').setValue(false);
      this.toggleGroupSelect(index);
    });
  }

  // 获取所有选中的选项(用于提交或展示)
  getSelectedItems(): any[] {
    const selected = [];
    this.groups.controls.forEach((_, groupIndex) => {
      const groupLabel = this.groupData[groupIndex].label;
      const items = this.getGroupItems(groupIndex);
      items.controls.forEach((control, itemIndex) => {
        if (control.value) {
          selected.push({
            group: groupLabel,
            title: this.groupData[groupIndex].data[itemIndex].title
          });
        }
      });
    });
    return selected;
  }
}

3. 模板代码

在组件模板中渲染分组复选框面板:

<form [formGroup]="mainForm" class="checkbox-container">
  <!-- 全局控制按钮 -->
  <div class="global-controls">
    <button type="button" (click)="selectAll()" class="btn btn-primary">全选所有</button>
    <button type="button" (click)="deselectAll()" class="btn btn-secondary ml-2">取消全选</button>
  </div>

  <!-- 分组复选框面板 -->
  <div formArrayName="groups" class="group-panels">
    <div *ngFor="let group of groups.controls; let i = index" 
         [formGroupName]="i" 
         class="group-panel card mt-3 p-3">
      <!-- 组全选复选框 -->
      <div class="group-header">
        <input type="checkbox" 
               formControlName="groupSelect" 
               (change)="toggleGroupSelect(i)"
               class="mr-2">
        <label>{{ groupData[i].label }}</label>
      </div>

      <!-- 组内选项列表 -->
      <div formArrayName="items" class="group-items mt-2">
        <div *ngFor="let item of getGroupItems(i).controls; let j = index" 
             class="item-checkbox">
          <input type="checkbox" 
                 [formControlName]="j" 
                 (change)="onItemChange(i)"
                 class="mr-2">
          <label>{{ groupData[i].data[j].title }}</label>
        </div>
      </div>
    </div>
  </div>

  <!-- 可选:展示选中结果 -->
  <div class="selected-result mt-4">
    <h4>已选中选项:</h4>
    <ul>
      <li *ngFor="let item of getSelectedItems()">{{ item.group }} - {{ item.title }}</li>
    </ul>
  </div>
</form>

4. 基础样式(可选)

添加简单样式优化界面展示:

.checkbox-container {
  max-width: 800px;
  margin: 20px auto;
  padding: 0 20px;
}

.global-controls {
  margin-bottom: 20px;
}

.group-panel {
  border: 1px solid #eee;
  border-radius: 4px;
}

.group-header {
  font-weight: bold;
  font-size: 1.1rem;
}

.group-items {
  margin-left: 20px;
}

.item-checkbox {
  margin: 8px 0;
}

.selected-result ul {
  list-style-type: none;
  padding-left: 0;
}

.selected-result li {
  padding: 4px 0;
  border-bottom: 1px solid #f0f0f0;
}

功能说明

  • 组内全选:点击分组标题旁的复选框,可一键选中/取消该组所有选项
  • 全局全选:点击顶部按钮可批量选中/取消所有分组的所有选项
  • 状态同步:手动勾选完组内所有选项时,分组全选框自动变为选中状态;取消任意选项则同步取消分组全选状态
  • 结果获取:通过getSelectedItems()方法可获取所有选中项的分组标签和标题,方便后续业务处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:57:35