基于动态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
相关产品推荐
相关产品推荐

