Angular 2 动态字段的表单验证
Angular 2 Form validation for dynamic fields
我正在做一个 Angular 4.X 项目,我正在创建一些 HTML 输入字段(主要是文本类型),点击按钮。动态创建输入框工作正常,但我无法对这些字段实施验证。我收到以下错误。
无法读取 null(…)
的 属性 'invalid'
我为此创建了一个 plunk。以下是我创建的 plunk 的 link --
https://plnkr.co/edit/PCFD43GK91zo2ivQ9lf7?p=preview
为了便于参考,请在下面找到代码 --
//Root app component
import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { FormBuilder, FormGroup, Validators, FormArray, FormControl } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'my-app',
template: `<hr>
<div>
<form [formGroup]="orderForm" (ngSubmit)="OnSubmit(orderForm.value)">
<div>
<input type="text" formControlName="customerName"/>
<input type="text" formControlName="email"/>
</div>
<div formArrayName="items" *ngFor="let item of items.controls; let i = index;">
<div [formGroupName]="i">
<input type="text" formControlName="name" placeholder="Item name"/>
<small *ngIf="IsValidField('name')" class="text-danger">
Name is required
</small>
<input type="text" formControlName="description" placeholder="Item description"/>
<small *ngIf="IsValidField('description')" class="text-danger">
Description is required
</small>
<input type="text" formControlName="price" placeholder="Item price"/>
<small *ngIf="IsValidField('price')" class="text-danger">
Price is required
</small>
</div>
Chosen name: {{ orderForm.controls.items.controls[i].controls.name.value }}
</div>
<button type="submit">Save</button>
<button type="button" (click)="addItem()">Add More</button>
</form>
<div>`,
})
export class App {
constructor(private formBuilder: FormBuilder) { }
public orderForm: FormGroup;
ngOnInit() {
this.orderForm = this.formBuilder.group({
customerName: '',
email: '',
items: this.formBuilder.array([ this.createItem()])
});
}
createItem(): FormGroup {
return this.formBuilder.group({
name: ['',[Validators.required,Validators.maxLength(10)]],
description: '',
price: ['',[Validators.required,Validators.pattern("[(0-9)*]")]]
});
}
get items(): FormArray {
return this.orderForm.get('items') as FormArray;
};
addItem(): void {
this.items.push(this.createItem());
}
public OnSubmit(formValue: any) {
console.log(JSON.stringify(formValue));
}
public IsValidField(field: string) {
return (this.orderForm.get(field).invalid && this.orderForm.get(field).touched) || (this.orderForm.get(field).invalid && this.orderForm);
}
}
@NgModule({
imports: [ BrowserModule, FormsModule, ReactiveFormsModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
如有任何帮助,我们将不胜感激。
您正在 orderForm
中搜索动态添加的表单域,那里没有。您应该在访问其值之前正确查询表单。我画了下图,这将帮助你理解动态创建的表单架构。
orderForm (FormGroup)
|
- Items (FormArray)
|
- 0 (FormGroup)
- name
- description
- price
|
- 1 (FormGroup)
- name
- description
- price
|
|.........
所以IsValidField
函数应该获取formArray
元素的index
和字段名。通过它您可以轻松查询表单元素。
public IsValidField(i: number, field: any) {
var f = this.orderForm
.get('items') //retrieve items FormArray
.get(i.toString()) //retrieve items FormGroup
.get(field); //retrieve items form field
return (f.invalid && f.touched) || (f.invalid && this.orderForm);
}
然后相应地更改 *ngIf
上的 IsValidField
函数调用。
*ngIf="IsValidField(i, 'name')"
*ngIf="IsValidField(i, 'description')"
*ngIf="IsValidField(i, 'price')"
我正在做一个 Angular 4.X 项目,我正在创建一些 HTML 输入字段(主要是文本类型),点击按钮。动态创建输入框工作正常,但我无法对这些字段实施验证。我收到以下错误。
无法读取 null(…)
的 属性 'invalid'我为此创建了一个 plunk。以下是我创建的 plunk 的 link --
https://plnkr.co/edit/PCFD43GK91zo2ivQ9lf7?p=preview 为了便于参考,请在下面找到代码 --
//Root app component
import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { FormBuilder, FormGroup, Validators, FormArray, FormControl } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'my-app',
template: `<hr>
<div>
<form [formGroup]="orderForm" (ngSubmit)="OnSubmit(orderForm.value)">
<div>
<input type="text" formControlName="customerName"/>
<input type="text" formControlName="email"/>
</div>
<div formArrayName="items" *ngFor="let item of items.controls; let i = index;">
<div [formGroupName]="i">
<input type="text" formControlName="name" placeholder="Item name"/>
<small *ngIf="IsValidField('name')" class="text-danger">
Name is required
</small>
<input type="text" formControlName="description" placeholder="Item description"/>
<small *ngIf="IsValidField('description')" class="text-danger">
Description is required
</small>
<input type="text" formControlName="price" placeholder="Item price"/>
<small *ngIf="IsValidField('price')" class="text-danger">
Price is required
</small>
</div>
Chosen name: {{ orderForm.controls.items.controls[i].controls.name.value }}
</div>
<button type="submit">Save</button>
<button type="button" (click)="addItem()">Add More</button>
</form>
<div>`,
})
export class App {
constructor(private formBuilder: FormBuilder) { }
public orderForm: FormGroup;
ngOnInit() {
this.orderForm = this.formBuilder.group({
customerName: '',
email: '',
items: this.formBuilder.array([ this.createItem()])
});
}
createItem(): FormGroup {
return this.formBuilder.group({
name: ['',[Validators.required,Validators.maxLength(10)]],
description: '',
price: ['',[Validators.required,Validators.pattern("[(0-9)*]")]]
});
}
get items(): FormArray {
return this.orderForm.get('items') as FormArray;
};
addItem(): void {
this.items.push(this.createItem());
}
public OnSubmit(formValue: any) {
console.log(JSON.stringify(formValue));
}
public IsValidField(field: string) {
return (this.orderForm.get(field).invalid && this.orderForm.get(field).touched) || (this.orderForm.get(field).invalid && this.orderForm);
}
}
@NgModule({
imports: [ BrowserModule, FormsModule, ReactiveFormsModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
如有任何帮助,我们将不胜感激。
您正在 orderForm
中搜索动态添加的表单域,那里没有。您应该在访问其值之前正确查询表单。我画了下图,这将帮助你理解动态创建的表单架构。
orderForm (FormGroup)
|
- Items (FormArray)
|
- 0 (FormGroup)
- name
- description
- price
|
- 1 (FormGroup)
- name
- description
- price
|
|.........
所以IsValidField
函数应该获取formArray
元素的index
和字段名。通过它您可以轻松查询表单元素。
public IsValidField(i: number, field: any) {
var f = this.orderForm
.get('items') //retrieve items FormArray
.get(i.toString()) //retrieve items FormGroup
.get(field); //retrieve items form field
return (f.invalid && f.touched) || (f.invalid && this.orderForm);
}
然后相应地更改 *ngIf
上的 IsValidField
函数调用。
*ngIf="IsValidField(i, 'name')"
*ngIf="IsValidField(i, 'description')"
*ngIf="IsValidField(i, 'price')"