首先,有三种类型的表单 - FormControl、FormGroup 和 FormArray - 都继承自 AbstractControl。
当您使用响应式表单进行验证并在组件的模板中包含formGroupName、formControlName 或formArrayName 时,您实际上是在声明式地定义表单控件树和根FormGroup 模型之间的映射。
例如,给定以下模板:
<div [formGroup]="formGroup">
<div formGroupName="personalInfo">
First Name: <input type="text" formControlName="firstName"><br />
Last Name: <input type="text" formControlName="lastName"><br />
</div>
<div formArrayName="cities">
Top cities: <input *ngFor="let city of cities; index as i" type="text" [formControlName]="i">
</div>
</div>
您正在以声明方式设置用于收集信息的表单映射,最终将生成特定格式的 JSON 对象。例如,给定上述表单模型,formGroup.value 将返回:
{
"personalInfo": {
"firstName: 'John',
"lastName: 'Smith'
},
"cities": [
"New York",
"Winnipeg",
"Toronto"
]
}
在模板中声明表单组的结构后,您需要在组件类中强制创建相应的formGroup、formControl 和formArray。在设置每个表单时,您有机会设置其他参数:
1. Initial Form Value
2. Array of synchronous validators
3. Array of asynchronous validators
这适用于任何抽象控件。
这是给定上述模板的相应 formGroup 模型的样子:
export class AppComponent {
firstName: string,
lastName: string;
cities: string[];
@Input() formGroup: FormGroup;
constructor(private fb: FormBuilder) {
// setup initial values
this.cities = ['New York', 'Winnipeg', 'Toronto'];
this.firstName = 'John';
this.lastName = 'Smith';
// create a formGroup that corresponds to the template
this.formGroup = fb.group({
firstName: [this.firstName, Validators.required],
lastName: [this.lastName, Validators.required],
cities: fb.array(this.cities.map(t=> fb.control(t, Validators.required)))
})
}
}
要绑定到任何表单的验证标志,您可以使用根 formGroup 和路径字符串(支持点)来查找特定的组、控件或数组。
例如:
<div *ngIf="formGroup.get('firstName').errors.required">First Name is Required</div>
希望这能说明问题。
[编辑]
更好的是,鉴于 Reactive Forms 就是在模板中以声明方式设置模型,并在组件类中强制映射相同的模型,您应该考虑定义 JSON 模型并改用它。
例如,假设我们有一个自定义模型MyModel,它具有firstName 属性、lastName 属性和cities 属性。组件类看起来像这样:
export class AppComponent {
@Input() model: MyModel;
@Output() modelChange: EventEmitter<MyModel>;
@Input() formGroup: FormGroup;
constructor(private fb: FormBuilder) {
this.model = new EventEmitter<MyModel>();
// create a formGroup that corresponds to the template
this.formGroup = fb.group({
firstName: [this.model.firstName, Validators.required],
lastName: [this.model.lastName, Validators.required],
cities: fb.array(this.model.cities.map(t=> fb.control(t, Validators.required)))
});
}
onSubmit() {
if (this.formGroup.valid) {
this.model = this.formGroup.value;
this.modelChange.next(this.model);
}
}
}