Angular 6中用FormArray实现动态问答表单的单选按钮问题
解决FormArray中单选按钮互斥失效的问题
你的问题根源在于:每个选项的isCorrect控件属于各自的formGroupName,导致原生单选按钮的name属性被Angular自动生成为不同值(比如options-0-isCorrect、options-1-isCorrect),而原生单选按钮只有相同name属性才会触发互斥选中的行为。同时,每个isCorrect是独立的FormControl,切换时不会自动将其他选项的状态置为未选中。
下面提供两种解决方案,你可以根据现有代码情况选择:
方案一:快速修复现有结构
修改HTML
给所有单选按钮设置相同的name属性,并在change事件中传递当前选项的索引:
<form [formGroup]="questionForm"> <button type="button" class="iconBtn" title="Add Options" (click)="addOptions()"> Add Option </button> <div formArrayName="options"> <div *ngFor="let option of questionForm.controls['options'].controls; let i = index"> <div class="row" [formGroupName]='i'> <div class="col-xs-1 text-right"> <span class="radio"> <label class="radio-inline" title="Select if this is correct answer"> <input type="radio" [formControlName]="'isCorrect'" value="1" name="correctOption" <!-- 统一name属性 --> (change)="selectCorrectOption(i)"/> <!-- 传递当前索引 --> </label> </span> </div> <div class="col-xs-11"> <input type="text" class="form-control" placeholder="Option Text" [formControlName]="'optionText'"/> </div> </div> </div> </div> </form>
修改TypeScript
在selectCorrectOption方法中手动遍历所有选项,将选中项的isCorrect设为1,其余设为0:
selectCorrectOption(selectedIndex: number) { const optionsArray = this.questionForm.get('options') as FormArray; optionsArray.controls.forEach((control, index) => { // 给非选中项的isCorrect设为0,选中项设为1 control.get('isCorrect')?.setValue(index === selectedIndex ? 1 : 0); }); }
方案二:重构表单结构(更优)
从业务逻辑来看,正确选项只有一个,没必要给每个选项都单独存储isCorrect状态。我们可以新增一个单独的FormControl来存储正确选项的索引,这样更符合表单设计的合理性:
修改TypeScript
调整表单初始化和添加选项的逻辑:
ngOnInit() { this.questionForm = this._fb.group({ 'options': this._fb.array([ this._fb.group({ 'optionText': [''] }) ]), 'correctOptionIndex': [0] // 新增控件,存储正确选项的索引 }); } public addOptions() { let control = <FormArray>this.questionForm.controls.options; control.push(this._fb.group({ 'optionText': [''] })); }
修改HTML
让所有单选按钮绑定到correctOptionIndex控件,通过value传递当前选项的索引:
<form [formGroup]="questionForm"> <button type="button" class="iconBtn" title="Add Options" (click)="addOptions()"> Add Option </button> <div formArrayName="options"> <div *ngFor="let option of questionForm.controls['options'].controls; let i = index"> <div class="row" [formGroupName]='i'> <div class="col-xs-1 text-right"> <span class="radio"> <label class="radio-inline" title="Select if this is correct answer"> <input type="radio" [value]="i" [formControl]="questionForm.get('correctOptionIndex')" /> </label> </span> </div> <div class="col-xs-11"> <input type="text" class="form-control" placeholder="Option Text" [formControlName]="'optionText'"/> </div> </div> </div> </div> </form>
这种方案的优势在于:
- 原生单选按钮的互斥行为会自动生效(因为它们绑定到同一个FormControl)
- 表单数据结构更简洁,后续获取正确选项时只需通过
correctOptionIndex找到对应索引的选项即可
内容的提问来源于stack exchange,提问作者OM PRAKASH
相关产品推荐
相关产品推荐

