Angular实现下拉框选中项移除、删标签后恢复选项的方法
Angular 实现下拉选择与标签双向联动效果
实现目标
下拉选择组件选中选项后自动生成对应标签,需补充两个交互规则:
- 选项被选中后自动从下拉列表移除,避免重复选择
- 已生成的标签被删除时,对应选项自动恢复到下拉列表,支持再次选择

核心实现思路
不直接用传入的全量选项渲染下拉列表,单独维护一份实时可选选项列表,始终保证:可选选项 = 全量选项 - 已生成标签对应的选项
每次选中选项、删除标签时同步更新这份可选列表即可。
具体代码实现
1. 组件类(TS)调整
import { Component, Input, OnInit, OnDestroy } from '@angular/core'; import { BehaviorSubject, Observable, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; export class SelectWithTagInputComponent implements OnInit, OnDestroy { @Input() filteredProperty: EnumRowConfigDto; @Input() inputOptions: Observable<IOption[]>; @Input() labelFilter: string; defaultSelectedValue = null; // 下拉框实际渲染的可选选项流 availableOptions$ = new BehaviorSubject<IOption[]>([]); // 全量选项备份,用于计算可选列表 private allOptions: IOption[] = []; // 销毁订阅用 private destroy$ = new Subject<void>(); ngOnInit(): void { // 订阅全量选项数据源,初始化可选列表 this.inputOptions .pipe(takeUntil(this.destroy$)) .subscribe(allOpts => { this.allOptions = allOpts; this.updateAvailableOptions(); }); } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } // 下拉选中事件 selectedOption(value): void { let filterData; if (typeof value === 'string') { filterData = JSON.parse(value); filterData.name = filterData.value; delete filterData.value; } else { filterData = value; } // 避免重复添加标签 const hasExisted = this.filteredProperty.filters.some(el => el.name === filterData.name); if (!hasExisted) { this.filteredProperty.filters.push(filterData); // 添加标签后更新可选列表,移除已选选项 this.updateAvailableOptions(); } // 重置下拉框到默认提示项 this.defaultSelectedValue = null; } // 标签删除回调 setDefaultOptionSelect(): void { this.defaultSelectedValue = null; // 删除标签后更新可选列表,恢复对应选项 this.updateAvailableOptions(); } // 计算当前可选选项:过滤掉已生成标签的选项 private getAvailableOptions(): IOption[] { const selectedValues = this.filteredProperty.filters.map(item => item.name); return this.allOptions.filter(opt => !selectedValues.includes(opt.value)); } // 推送最新可选选项到视图 private updateAvailableOptions(): void { this.availableOptions$.next(this.getAvailableOptions()); } } // 类型定义(可根据项目实际类型调整) interface IOption { label: string; value: string | number; } interface EnumDto { name: string | number; label: string; } interface EnumRowConfigDto { filters: EnumDto[]; }
2. 模板(HTML)调整
仅需要把下拉框的选项循环源从原来的inputOptions | async替换为我们维护的availableOptions$ | async,标签组件部分原有逻辑无需改动:
<select class="form-control" id="{{labelFilter | removewhitespaces}}" name="{{labelFilter | removewhitespaces}}" [(ngModel)]="defaultSelectedValue" (change)="selectedOption($event.target['value'])"> <option [value]="null" disabled selected>{{labelFilter}}</option> <!-- 绑定过滤后的可选选项列表 --> <option *ngFor="let option of availableOptions$ | async" [value]="option | json"> {{option.label}} </option> </select> <tag-input *ngIf="filteredProperty.filters.length" [(ngModel)]="filteredProperty.filters" [class.full-width]="filteredProperty.filters.length" (onRemove)="setDefaultOptionSelect()" [identifyBy]="'name'" [displayBy]="'label'" [placeholder]="''" [secondaryPlaceholder]="''"> </tag-input>
补充说明:如果全量选项是动态变更的(比如从接口拉取、搜索过滤),只需要在全量选项更新后调用
updateAvailableOptions()重新计算可选列表即可,逻辑可直接复用。
内容的提问来源于stack exchange,提问作者Artamiel
相关产品推荐
相关产品推荐

