Angular父组件集成动态子表单组件的三个相关问题
Angular自定义文本框子组件接入父组件FormGroup解决方案
1. 子组件接入父组件FormGroup的实现方式
子组件需要实现Angular的ControlValueAccessor接口,同时在组件的providers数组中注册NG_VALUE_ACCESSOR令牌,即可将子组件作为独立表单控件接入父组件的FormGroup:
- 子组件核心代码示例:
// 子组件ts文件 import { Component, forwardRef, Input } from '@angular/core'; import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; @Component({ selector: 'app-custom-input', template: `<input [formControl]="inputControl" [name]="inputName"/>`, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CustomInputComponent), multi: true } ] }) export class CustomInputComponent implements ControlValueAccessor { inputControl = new FormControl(); private onChange = (value: any) => {}; private onTouched = () => {}; writeValue(value: any): void { this.inputControl.setValue(value, { emitEvent: false }); } registerOnChange(fn: any): void { this.onChange = fn; this.inputControl.valueChanges.subscribe(fn); } registerOnTouched(fn: any): void { this.onTouched = fn; } setDisabledState?(isDisabled: boolean): void { isDisabled ? this.inputControl.disable() : this.inputControl.enable(); } }
- 父组件使用方式:在父组件的FormGroup中声明对应控件后,直接用
formControlName绑定即可
<!-- 父组件模板 --> <form [formGroup]="parentForm"> <app-custom-input formControlName="customField"></app-custom-input> </form>
2. 按需添加required校验器的实现
通过子组件的@Input()属性接收是否必填的配置,动态给子组件内部的FormControl添加/移除required校验:
- 子组件新增输入属性代码:
@Input() set required(value: boolean) { if (value) { this.inputControl.addValidators(Validators.required); } else { this.inputControl.removeValidators(Validators.required); } this.inputControl.updateValueAndValidity(); }
- 父组件按需传值即可:
<!-- 需要必填的场景 --> <app-custom-input formControlName="field1" [required]="true"></app-custom-input> <!-- 不需要必填的场景 --> <app-custom-input formControlName="field2" [required]="false"></app-custom-input>
3. 动态设置name字段的实现
同样通过@Input()属性接收name值,绑定到内部input元素的name属性即可,同一父组件多次使用时传不同的name值即可:
- 子组件新增输入属性:
@Input() inputName: string = '';
- 子组件模板绑定name:
<input [formControl]="inputControl" [name]="inputName"/>
- 父组件多次使用时传不同name:
<app-custom-input formControlName="field1" inputName="field1" [required]="true"></app-custom-input> <app-custom-input formControlName="field2" inputName="field2" [required]="false"></app-custom-input> <app-custom-input formControlName="field3" inputName="field3" [required]="true"></app-custom-input>
内容的提问来源于stack exchange,提问作者mnu-nasir
相关产品推荐
相关产品推荐

