Angular问题:自定义输入组件无法向FormGroup的test控件传值
解决Angular自定义表单组件值同步到父FormControl的问题
看起来你在实现ControlValueAccessor时走了点弯路,问题主要出在内部额外创建了FormGroup以及没有正确调用onChange回调来通知父组件值变化上。下面是修复后的完整方案:
第一步:修改自定义组件的HTML模板
去掉内部的<form>和FormGroup绑定,我们要通过ControlValueAccessor直接和父表单的FormControl关联,不需要自己套一层表单:
<div class="col-sm-6 col-xs-12"> <div class="form-group"> <label class="col-sm-5"> {{label}} <span *ngIf="required" class="required">*</span> </label> <div class="col-sm-7"> <input type="text" class="form-control" [(ngModel)]="inputData" (input)="onInputChange(inputData)" (blur)="onTouched()" [disabled]="isDisabled" /> </div> </div> </div>
(注:我把你的lable拼写修正成了标准的label)
第二步:重写自定义组件的TS代码
简化逻辑,正确实现ControlValueAccessor的核心方法,去掉不必要的内部FormGroup和EventEmitter:
import { Component, OnInit, Input, forwardRef } from '@angular/core'; import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; @Component({ selector: 'proj-form-row-input', templateUrl: './form-row-input.component.html', styleUrls: ['./form-row-input.component.css'], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FormRowInputComponent), multi: true } ] }) export class FormRowInputComponent implements OnInit, ControlValueAccessor { @Input() public label: string; @Input() public required: boolean = false; public inputData: string = ''; public isDisabled: boolean = false; private onChange: (value: string) => void = () => {}; private onTouched: () => void = () => {}; ngOnInit() { } // 接收父组件FormControl传来的值,同步到内部输入框 writeValue(obj: string): void { if (obj !== this.inputData) { this.inputData = obj || ''; } } // 注册值变化回调(父组件会传入这个函数,我们用它通知值变化) registerOnChange(fn: any): void { this.onChange = fn; } // 注册触摸回调(用于表单的touched状态校验) registerOnTouched(fn: any): void { this.onTouched = fn; } // 同步父组件的禁用状态到内部输入框 setDisabledState(isDisabled: boolean): void { this.isDisabled = isDisabled; } // 内部输入框值变化时,通知父组件的FormControl onInputChange(value: string): void { this.inputData = value; this.onChange(value); // 关键:调用这个回调完成值同步 } }
关键修复点解释
- 移除内部FormGroup:自定义表单组件通过
ControlValueAccessor和父表单的FormControl直接绑定,自己维护独立FormGroup会切断这种关联,完全没必要。 - 正确调用
onChange:这是值同步到父FormControl的核心!当内部输入框值变化时,必须调用registerOnChange保存的回调函数,把最新值传递给父组件。 - 简化
writeValue逻辑:这个方法只需要接收父组件传来的值,同步到内部输入框即可,不需要额外发射事件。 - 完善禁用状态同步:实现
setDisabledState方法,确保父组件设置控件禁用时,内部输入框也会同步禁用。 - 移除多余的
EventEmitter:ControlValueAccessor已经完成了值双向同步的工作,不需要额外通过@Output发射事件。
这样修改后,父页面里的formControlName="test"就能实时获取到自定义组件的输入值了。
内容的提问来源于stack exchange,提问作者Anuwat J. Boonlao
相关产品推荐
相关产品推荐

