Angular多选下拉框如何单独取消已选项(关联动态FormGroup)
你现在的问题是用this.selectModel.reset()会清空所有选中项,要实现只取消删除的那个FormGroup对应的下拉选项,核心思路是从双向绑定的selectedLevel数组中移除对应的语言项,而不是重置整个下拉控件。下面是具体的修改步骤和代码:
第一步:完善FormGroup的创建,关联选中的语言
首先,你的addSkillFormGroup方法需要接收选中的语言作为参数,把它赋值给skillName控件,这样每个FormGroup都能和对应的下拉选项关联起来:
addSkillFormGroup(skillName: string) { return this.fb.group({ skillName: [skillName, Validators.required], // 传入选中的语言名称 experienceInYears: ['', Validators.required], proficiency: ['', Validators.required] }); }
然后修改selected方法,注意多选下拉框的selectedLevel是一个数组,每次选择变化时,应该计算新增的选项(避免重复添加FormGroup),然后为每个新增的选项创建对应的FormGroup:
selected(event) { // 获取当前已有的技能名称集合 const existingSkills = (this.userForm.get('skills') as FormArray).controls.map(ctrl => ctrl.get('skillName').value); // 筛选出本次新增的未存在的语言 const newSkills = this.selectedLevel.filter(skill => !existingSkills.includes(skill)); newSkills.forEach(skill => { (this.userForm.get('skills') as FormArray).push(this.addSkillFormGroup(skill)); }); this.isItConfirmed = true; }
(注:原来的写法每次触发change都会添加一个FormGroup,可能会重复,上面的代码避免了重复添加同一个语言的FormGroup)
第二步:修改删除方法,移除对应下拉选项
现在在removeSkillButtonClick方法中,我们需要:
- 获取要删除的FormGroup对应的
skillName - 从
selectedLevel数组中移除该语言 - 删除对应的FormGroup
修改后的代码:
removeSkillButtonClick(skillGroupIndex: number) { // 获取要删除的技能名称 const skillToRemove = (this.userForm.get('skills') as FormArray).controls[skillGroupIndex].get('skillName').value; // 从selectedLevel数组中移除该技能(保持数组引用,触发双向绑定更新) this.selectedLevel = this.selectedLevel.filter(skill => skill !== skillToRemove); // 删除对应的FormGroup (this.userForm.get('skills') as FormArray).removeAt(skillGroupIndex); // 如果没有剩余技能,隐藏表单区域 if ((this.userForm.get('skills') as FormArray).length === 0) { this.isItConfirmed = false; } }
这里不再使用this.selectModel.reset(),而是通过修改selectedLevel数组(双向绑定的变量),让下拉框自动更新选中状态,只移除对应的选项。
第三步:修正HTML中的变量错误
你的HTML模板里有几处{{item}}是错误的,因为在*ngFor="let skill of userForm.get('skills').controls"的循环中,item已经不存在了,应该替换为当前FormGroup的skillName值:
<div class="forma" *ngIf="isItConfirmed" [formGroup]="userForm"> <div formArrayName="skills" *ngFor="let skill of userForm.get('skills').controls; let i = index"> <div [formGroupName]="i"> <div class="form-group"> <label class="col-sm-2 control-label" [attr.for]="'skillName' + i"> {{skill.get('skillName').value}} </label> </div> <div class="form-group"> <label class="col-sm-2 control-label" [attr.for]="'experienceInYears' + i"> Set the experience in years for {{skill.get('skillName').value}} </label> <div class="col-sm-4"> <input type="text" class="form-control" [id]="'experienceInYears' + i" formControlName="experienceInYears" placeholder="In Years"> </div> </div> <div class="form-group"> <label class="col-md-2 control-label">Set the Proficiency level for {{ skill.get('skillName').value }}</label> <div class="col-md-8"> <label class="radio-inline"> <input type="radio" value="beginner" formControlName="proficiency">Beginner </label> <label class="radio-inline"> <input type="radio" value="intermediate" formControlName="proficiency">Intermediate </label> <label class="radio-inline"> <input type="radio" value="advanced" formControlName="proficiency">Advanced </label> </div> </div> <div class="col-sm-6" *ngIf="userForm.get('skills')"> <button type="button" class="btn btn-danger btn-sm pull-right" title="Delete Skill" (click)="removeSkillButtonClick(i)"> Remove <span class="glyphicon glyphicon-remove"></span> </button> </div> <div class="hr"></div> </div> </div> </div>
补充:初始化FormGroup的代码
确保你在组件的ngOnInit中正确初始化了userForm,比如:
constructor(private fb: FormBuilder) {} ngOnInit() { this.userForm = this.fb.group({ skills: this.fb.array([]) }); }
这样整个流程就通顺了:选中下拉选项时添加对应的FormGroup,删除FormGroup时只移除对应的下拉选项,而不会清空所有选中项。
内容的提问来源于stack exchange,提问作者Code

