Reactive Forms结合ControlValueAccessor自定义控件赋值未生效问题
问题根因
你遇到的问题是由两处核心配置和实现缺失导致的:
- 第一,自定义表单控件
TextboxComponent没有注册NG_VALUE_ACCESSOR提供者,Angular表单无法识别该组件为合法的表单控件,因此不会主动调用writeValue方法同步表单值到控件内部,这就是你表单已经赋值,但输入框没有显示的直接原因。 - 第二,
TextboxComponent内部的ControlValueAccessor实现不完整:- 你当前给
onChange、onTouch写的是TypeScript类型声明,没有赋初始空函数,后续调用会抛出undefined错误 - 值变更的setter中没有调用
onChange回调,输入框内容变更时无法同步回上层表单 writeValue没有做空值兼容,表单赋null/undefined时会有异常
- 你当前给
修复后的TextboxComponent代码
import { Component, OnInit, forwardRef } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; @Component({ selector: 'app-textbox', template: ` <input [(ngModel)]="value" [disabled]="disabled" /> `, styleUrls: ['./textbox.component.css'], // 新增:注册NG_VALUE_ACCESSOR,告诉Angular这是合法的表单控件 providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TextboxComponent), multi: true } ] }) export class TextboxComponent implements OnInit, ControlValueAccessor { constructor() { } writeValue(obj: any): void { // 新增空值兼容 this._value = obj ?? ''; } registerOnChange(fn: any): void { this.onChange = fn; } registerOnTouched(fn: any): void { this.onTouch = fn; } setDisabledState?(isDisabled: boolean): void { this.disabled = isDisabled; } disabled = false; // 修正:赋初始空函数,不是只声明类型 onChange = (val: string) => {} onTouch = () => {}; private _value:string = ''; public get value():string { return this._value } public set value(value:string){ this._value = value; // 新增:值变更时通知上层表单 this.onChange(value); this.onTouch(); } ngOnInit(): void { } }
补充说明
修复后重新运行,表单赋值的test就会正常显示在输入框中,同时你在输入框中修改内容也会同步回上层FormGroup的对应控件。
内容的提问来源于stack exchange,提问作者3xGuy
相关产品推荐
相关产品推荐

