Angular中ControlValueAccessor组件writeValue触发valueChange致字段清空问题
解决ControlValueAccessor组件中writeValue触发valueChanges导致字段清空的问题
问题根源很明确:writeValue里调用setValue更新name字段时,会触发name的valueChanges订阅,进而执行patchValue({version: null}),直接覆盖了你传入的version值。
这里提供两种实用的解决方案:
方案一:用标志位区分操作来源
在组件内添加一个临时标志,标记当前是否处于writeValue执行阶段,只有非该阶段触发的valueChanges才执行清空version的逻辑:
// 组件内定义标志位 private isWritingValue = false; ngOnInit() { this.formGroup.get('name')?.valueChanges.subscribe(x => { // 仅当不是writeValue触发时,才清空version if (!this.isWritingValue) { this.formGroup.patchValue({version: null}); } }); } writeValue(value: {name: string, version: any}) { this.isWritingValue = true; this.formGroup.setValue({ name: value.name, version: value.version }); // 执行完毕后重置标志 this.isWritingValue = false; this.changeDetectorRef.markForCheck(); }
方案二:设置setValue时不触发valueChanges
利用Angular表单的emitEvent选项,在writeValue调用setValue时禁止触发valueChanges事件,从根源避免订阅逻辑被执行:
writeValue(value: {name: string, version: any}) { this.formGroup.setValue( { name: value.name, version: value.version }, { emitEvent: false } // 禁用setValue时触发valueChanges ); this.changeDetectorRef.markForCheck(); }
两种方案对比
- 方案一灵活性更高:如果后续需要在
writeValue执行时部分触发订阅逻辑,只需调整标志位的判断条件即可。 - 方案二更简洁:直接阻断事件触发,适合不需要在
writeValue时执行任何订阅逻辑的场景。
内容的提问来源于stack exchange,提问作者Gargoyle
相关产品推荐
相关产品推荐

