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

Angular mat-select多选:切换数据源后保留历史已选值

解决方案:保留已选历史数据同时限制下拉可选范围

要实现显示已保存的非在售车辆(car2、car5),同时仅允许选择在售车辆(carsSold),可以通过合并数据源+禁用非在售选项的方式实现,具体步骤如下:

1. 组件中构造合并后的下拉数据源

在组件类中创建计算属性,合并在售车辆数组和已选的非在售车辆,确保已保存的历史选择能出现在下拉列表中:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators, AbstractControl, ValidationErrors } from '@angular/forms';

@Component({
  selector: 'app-shop-form',
  templateUrl: './shop-form.component.html'
})
export class ShopFormComponent implements OnInit {
  shopForm!: FormGroup;
  // 原始全量车辆数据
  cars = [
    { id: 1, name: "car1", sold: true },
    { id: 2, name: "car2", sold: false },
    { id: 3, name: "car3", sold: true },
    { id: 4, name: "car4", sold: true },
    { id: 5, name: "car5", sold: false }
  ];
  // 在售车辆数据源
  carsSold = [
    { id: 1, name: "car1", sold: true },
    { id: 3, name: "car3", sold: true },
    { id: 4, name: "car4", sold: true }
  ];

  constructor(private fb: FormBuilder) {}

  ngOnInit(): void {
    // 初始化表单,加载数据库保存的已选车辆ID
    this.shopForm = this.fb.group({
      carIds: [[1,2,5], [Validators.required, this.validateSoldCars()]]
    });
  }

  // 构造下拉列表用的合并数据源
  get dropdownCars() {
    const selectedIds = this.shopForm.get('carIds')?.value || [];
    // 筛选出已选但不在在售列表中的车辆
    const selectedNonSold = this.cars.filter(car => 
      selectedIds.includes(car.id) && !this.carsSold.some(s => s.id === car.id)
    );
    // 合并并去重,避免在售车辆重复显示
    return [...this.carsSold, ...selectedNonSold].filter((car, idx, self) => 
      self.findIndex(c => c.id === car.id) === idx
    );
  }

  // 可选:自定义验证器,确保提交时仅包含在售车辆
  validateSoldCars(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      const selectedIds = control.value as number[];
      const validIds = this.carsSold.map(c => c.id);
      const invalidIds = selectedIds.filter(id => !validIds.includes(id));
      return invalidIds.length > 0 ? { invalidNonSold: '不能选择已下架车辆' } : null;
    };
  }
}

2. 修改HTML模板,配置下拉选项

在模板中使用合并后的数据源,并对非在售车辆设置禁用状态,同时添加标记提示用户:

<mat-form-field>
    <mat-label>Cars</mat-label>
    <mat-select formControlName="carIds" multiple required>
      <mat-option 
        *ngFor="let car of dropdownCars" 
        [value]="car.id"
        [disabled]="!car.sold"
      >
        {{car.name}}
        <!-- 给非在售车辆添加视觉标记 -->
        <span *ngIf="!car.sold" style="color: #999;"> [已下架]</span>
      </mat-option>
    </mat-select>
    <!-- 显示验证错误信息 -->
    <mat-error *ngIf="shopForm.get('carIds')?.hasError('invalidNonSold')">
      {{shopForm.get('carIds')?.getError('invalidNonSold')}}
    </mat-error>
</mat-form-field>

效果说明

  • 打开表单时,已保存的car1、car2、car5都会显示在已选区域中
  • 下拉列表仅展示在售车辆(car1、car3、car4)和已选的非在售车辆(car2、car5)
  • 非在售车辆选项被禁用,无法被重新选择,但已选状态会保留
  • 可选的自定义验证器会阻止用户提交包含非在售车辆的表单(如果需要)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 12:10:56