Angular切换按钮控制的复选框勾选状态丢失问题求助
问题解决:切换显示隐藏后复选框勾选状态丢失
问题重现
- 页面加载:仅当切换按钮为“oui”时复选框可见,流程正常
- 勾选“invalidité”复选框,触发输入元素显示,流程正常
- 切换按钮至“no”,所有复选框隐藏,流程正常
- 再次切回“oui”时,复选框的勾选标记消失,出现异常
问题根源分析
- 子组件未实现表单双向同步:复选框组件的
ControlValueAccessor核心方法全部为空实现,导致视图勾选状态无法同步到FormControl模型,同时模型值也无法反向更新视图状态。 - 父组件未同步表单控件值:父组件的
isInvalidityCheckboxChecked方法仅更新了本地变量isInvalidityChecked,但没有修改对应FormControl的实际值,导致表单模型始终保留初始的false。 - 组件销毁重建重置状态:如果使用
*ngIf控制复选框显示隐藏,组件会被销毁再重建,此时会从表单模型读取初始值,而非之前的勾选状态。
修复方案
1. 完善复选框子组件的表单绑定逻辑
子组件HTML修改
为复选框input绑定FormControl,确保视图与模型联动:
<div class="c-form__tooltip align-items-center u-margin-bottom& md u-margin-bottom sm@tablet"> <div class="c-input-checkbox-list u-margin-bottom-sm" [ngClass]="{'error' : control.invalid && control.touched}"> <input type="checkbox" name="{{ formControlName }}" id="{{ formControlName }}" [formControl]="control" (change)="checkValue($event)" > <label for="{{ formControlName }}">{{ page + '.' + formControlName | translate }}</label> </div> <div class="c-tooltip"> <i class="c-tooltip__icon icon-question-circle-5"></i> <span class="c-tooltip__text" style="width:450px"> tooltip test temporaire </span> </div> </div>
子组件TS实现完整的ControlValueAccessor
补全表单同步的核心方法:
export class CheckBoxComponent implements ControlValueAccessor { @Input() public formControl: FormControl; @Input() public formControlName: string; @Input() public page: string; @Input() public index: number = 0; @Output() public onChecked: EventEmitter<boolean> = new EventEmitter<boolean>(); @ViewChild(FormControlDirective, {static: true}) public formControlDirective: FormControlDirective; onChange: (value: boolean) => void = () => {}; onTouched: () => void = () => {}; get control(): FormControl { return this.formControl || this.controlContainer.control.get(this.formControlName) as FormControl; } constructor(private controlContainer: ControlContainer) { } public registerOnTouched(fn: () => void): void { this.onTouched = fn; } public registerOnChange(fn: (value: boolean) => void): void { this.onChange = fn; } public writeValue(value: boolean): void { this.control.setValue(value); } public setDisabledState(isDisabled: boolean): void { isDisabled ? this.control.disable() : this.control.enable(); } public checkValue(event: Event): void { const isChecked = (event.target as HTMLInputElement).checked; this.onChange(isChecked); this.onChecked.emit(isChecked); this.onTouched(); } }
2. 修复父组件的表单值同步逻辑
修改isInvalidityCheckboxChecked方法,确保勾选状态同步到FormControl:
public isInvalidityCheckboxChecked(isChecked: Event): void { const checked = (isChecked.target as HTMLInputElement).checked; this.isInvalidityChecked = checked; // 同步更新表单控件的值 this.form.controls.invalidityCheckbox.setValue(checked); if (checked) { Solutions03CurrentProtectionComponent.addControlsInvalidity(this.form.controls.invalidity as FormGroup); } else { Solutions03CurrentProtectionComponent.removeControlsInvalidity(this.form.controls.invalidity as FormGroup); } }
3. 避免组件销毁重置状态(可选)
如果之前使用*ngIf控制显示,改为[hidden](仅隐藏DOM,不销毁组件):
<!-- 替换原*ngIf写法 --> <amp-check-box [hidden]="!isPensionContract" [formControl]="form.controls.invalidityCheckbox" [formControlName]="'invalidityCheckbox'" [page]="page" (onChecked)="isInvalidityCheckboxChecked($event)"> </amp-check-box>
验证步骤
- 切换按钮至“oui”,勾选复选框,确认
form.controls.invalidityCheckbox的值变为true - 切换按钮至“no”,复选框隐藏
- 切回“oui”,复选框的勾选状态应正常保留,表单控件值仍为
true
内容的提问来源于stack exchange,提问作者Olivier
相关产品推荐
相关产品推荐

