首先,有三种类型的表格 -FormControl
, FormGroup
, and FormArray
- 全部继承自AbstractControl
.
当您使用反应式表单进行验证并包括formGroupName
, formControlName
, or formArrayName
在组件的模板中,您实际上是在声明式定义表单控件树和根之间的映射FormGroup
model.
例如,给定以下模板:
<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
, and 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)))
})
}
}
要绑定到任何表单的验证标志,您可以使用 rootformGroup
以及用于查找特定组、控件或数组的路径字符串(支持点)。
例如:
<div *ngIf="formGroup.get('firstName').errors.required">First Name is Required</div>
希望这能够清楚地说明这一点。
[Edit]
更好的是,鉴于反应式表单主要是在模板中以声明方式设置模型,并在组件类中强制映射相同的模型,您应该考虑定义一个 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);
}
}
}