Angular中如何在下拉选项前添加复选框并实现多选及全选功能
实现带复选框的多选下拉(含全选功能)
原生<select>标签没办法直接给选项加复选框,我们可以自定义一个下拉组件来实现需求,结合Angular表单控件完成数据绑定:
1. 调整表单控件类型
把原来的单值FormControl改成FormArray(用来跟踪每个季节的选中状态),也可以用FormControl直接存储选中的ID数组,这里用FormArray更直观。
组件类代码:
import { Component } from '@angular/core'; import { FormBuilder, FormArray, FormControl } from '@angular/forms'; @Component({ selector: 'app-season-select', templateUrl: './season-select.component.html', styleUrls: ['./season-select.component.css'] }) export class SeasonSelectComponent { seasons = [ { id: 1, seasonNo: 1 }, { id: 2, seasonNo: 2 }, { id: 3, seasonNo: 3 } ]; seasonForm = this.fb.group({ selectedSeasons: this.fb.array([]) }); isDropdownOpen = false; get selectedSeasons(): FormArray { return this.seasonForm.get('selectedSeasons') as FormArray; } constructor(private fb: FormBuilder) { // 初始化FormArray,每个季节对应一个FormControl,默认未选中 this.seasons.forEach(() => this.selectedSeasons.push(new FormControl(false))); } // 全选/取消全选 toggleAll(event: Event) { const isChecked = (event.target as HTMLInputElement).checked; this.selectedSeasons.controls.forEach(control => { control.setValue(isChecked); }); } // 获取最终选中的季节ID数组 getSelectedSeasonIds(): number[] { return this.seasons .filter((_, index) => this.selectedSeasons.at(index).value) .map(season => season.id); } }
2. 编写模板HTML
用自定义结构模拟下拉框,包含触发按钮和带复选框的下拉面板:
<div class="custom-select-container"> <!-- 下拉触发按钮 --> <button class="form-select" (click)="isDropdownOpen = !isDropdownOpen" > {{ getSelectedSeasonIds().length > 0 ? `已选${getSelectedSeasonIds().length}个季节` : 'Select' }} </button> <!-- 下拉面板 --> <div class="dropdown-panel" *ngIf="isDropdownOpen"> <!-- 全选选项 --> <div class="dropdown-item"> <input type="checkbox" (change)="toggleAll($event)" [checked]="selectedSeasons.controls.every(c => c.value)" > <span>全选</span> </div> <!-- 季节选项列表 --> <div class="dropdown-item" *ngFor="let season of seasons; let i = index" > <input type="checkbox" [formControl]="selectedSeasons.at(i)" > <span>Season {{season.seasonNo}}</span> </div> </div> </div>
3. 添加基础样式
用CSS实现下拉面板的样式,模拟原生select的外观:
.custom-select-container { position: relative; width: fit-content; } .form-select { padding: 0.375rem 2.25rem 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; color: #212529; background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; cursor: pointer; min-width: 150px; } .dropdown-panel { position: absolute; top: 100%; left: 0; right: 0; border: 1px solid #ced4da; border-top: none; border-radius: 0 0 0.25rem 0.25rem; background-color: #fff; padding: 0.5rem; z-index: 1000; } .dropdown-item { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem; cursor: pointer; } .dropdown-item:hover { background-color: #f8f9fa; }
4. 表单值的使用
如果需要把选中的ID数组绑定到原有的formControlName="seasons",可以在提交时用getSelectedSeasonIds()获取值,赋值给对应的表单控件:
// 父组件提交逻辑示例 onSubmit() { const selectedIds = this.seasonSelectComponent.getSelectedSeasonIds(); this.parentForm.get('seasons')?.setValue(selectedIds); // 执行后续提交操作 }
内容的提问来源于stack exchange,提问作者Haris
相关产品推荐
相关产品推荐

