Angular中实现下拉框已选值不可重复选择的方案
实现已选食材不可重复选择的方案
当然可以实现这个需求啦!核心思路就是把已经被选中的食材从下拉选项里过滤掉,只让还没被选过的选项出现在新增行的下拉框中。下面是具体的实现步骤,结合你的代码来调整:
1. 在组件中添加过滤可用食材的方法
首先在你的AppComponent里新增一个方法,用来根据当前表单中已选的食材,过滤出还可以选择的选项。这里假设你的Ingredient接口有唯一标识id(如果没有的话,用name也可以,但要确保名称唯一):
getAvailableIngredients(currentIngredient?: Ingredient): Ingredient[] { // 从FormArray中提取所有已选中食材的id const selectedIds = (this.form.get('rows') as FormArray).controls .map(control => control.get('ingredientData')?.value?.id) .filter(id => id != null); // 如果是编辑已有行,要排除当前行自己的食材,避免编辑时自己的选项消失 const excludedIds = currentIngredient ? selectedIds.filter(id => id !== currentIngredient.id) : selectedIds; // 返回未被选中的食材列表 return this.ingredients.filter(ingredient => !excludedIds.includes(ingredient.id)); }
2. 修改模板中的下拉框代码
把原来遍历ingredients的逻辑,换成调用上面的过滤方法,同时传入当前行的已选食材(这样编辑已有行时,当前行的选项不会被过滤掉):
<!-- 假设你遍历FormArray的代码是类似这样的 --> <div formArrayName="rows" *ngFor="let row of form.get('rows').controls; let i = index"> <div [formGroupName]="i"> <div class="col-sm-12"> <select class="form-control" formControlName="ingredientData"> <option value="null" hidden>-- Select Ingredient --</option> <!-- 调用过滤方法,传入当前行的已选食材 --> <option *ngFor="let ingredient of getAvailableIngredients(row.get('ingredientData').value)" [ngValue]="ingredient"> {{ingredient.name}} </option> </select> </div> </div> </div>
3. 额外注意事项
- 如果你的
Ingredient没有id字段,可以用name替代id进行过滤,但必须保证食材名称是唯一的,否则会出现错误过滤的情况。 - 当你删除表单行时,被删除的食材会自动重新回到可选列表中,因为
selectedIds会随着FormArray的变化自动更新,过滤逻辑会实时生效。 - 如果遇到变更检测不及时的情况,可以注入
ChangeDetectorRef,在添加/删除行后调用cdr.detectChanges()手动触发更新。
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

