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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:53:11