angular2 formBuilder 组异步验证
angular2 formBuilder group async validation
我正在尝试实现异步验证器但没有成功...
我的组件创建了一个表单:
this.personForm = this._frmBldr.group({
lastname: [ '', Validators.compose([Validators.required, Validators.minLength(2) ]) ],
firstname: [ '', Validators.compose([Validators.required, Validators.minLength(2) ]) ],
birthdate: [ '', Validators.compose([ Validators.required, DateValidators.checkIsNotInTheFuture ]) ],
driverLicenceDate: [ '', Validators.compose([ Validators.required, DateValidators.checkIsNotInTheFuture ]), this.asyncValidationLicenceDate.bind(this) ],
}, {
asyncValidator: this.validateBusiness.bind(this),
validator: this.validateDriverLicenseOlderThanBirthdate,
});
我的验证方法
validateBusiness(group: FormGroup) {
console.log('validateBusiness')
return this._frmService
.validateForm(group.value)
.map((validationResponse: IValidationResponse) => {
if (validationResponse) {
validationResponse.validations.forEach( (validationError: IValidationErrorDescription) => {
let errorMsg = validationError.display;
let errorCode = validationError.code;
validationError.fields.forEach( (fieldName: string) => {
console.log(fieldName);
let control = this.personForm.controls[fieldName];
let existingErrors = control.errors || {};
existingErrors[errorCode] = errorMsg;
control.setErrors(existingErrors);
});
});
}
});
}
所有验证都被成功调用,除了从未调用过的 validateBusiness 方法(在 formbuilder.group
的 extra.asyncValidator
参数中)...有人可以告诉我我做错了什么吗?
发送
TL;DR: 通过分析您的用例,您可能需要解决方案 2
问题
问题在于异步验证器的定义和使用方式。
异步验证器定义为:
export interface AsyncValidatorFn {
(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
}
这是因为 FormBuilder.group()
实际上是在调用 FormGroup
构造函数:
constructor(controls: {
[key: string]: AbstractControl;
}, validator?: ValidatorFn | null, asyncValidator?: AsyncValidatorFn | null);
因此,异步验证器函数将接收一个 AbstractControl
实例,在本例中为 FormGroup
实例,因为验证器位于 FormGroup
级别。验证器需要 return Promise
或 ValidationErrors
的 Observable
,如果不存在验证错误则为 null。
ValidationErrors
被定义为字符串键和值(任何你喜欢的)的映射。键实际上是定义验证错误类型的字符串(例如:"required")。
export declare type ValidationErrors = {
[key: string]: any;
};
AbstractControl.setErrors()?
- 在您的示例中,您定义的函数不 return 任何东西,但实际上直接更改控制错误。调用 setErrors
仅适用于手动调用验证并因此仅手动设置错误的情况。相反,在您的示例中,方法是混合的,FormControl
s 附加了验证函数,它将自动 运行,FormGroup
异步验证函数,运行s 也自动尝试设置错误,从而手动设置有效性。这行不通。
您需要采用以下两种方法之一:
- 附加验证函数,它将 运行 自动设置错误和有效性。不要尝试在附加了验证功能的控件上手动设置任何内容。
- 手动设置错误和有效性,而不将任何验证函数附加到受影响的
AbstractControl
个实例。
如果你想保持一切干净,那么你可以继续实现单独的验证功能。 FormControl
验证将只处理一个控件。 FormGroup
验证会将表单组的多个方面视为一个整体。
如果您想使用验证服务,它实际上会验证整个表单,就像您所做的那样,然后将每个错误委托给每个适当的控件验证器,那么您可以使用解决方案 2.这个有点难。
但是如果您同意在 FormGroup
级别使用验证服务的验证器,那么可以使用 解决方案 1.[=73 来实现=]
解决方案 1 - 在 FormGroup 级别创建错误
假设我们要输入名字和姓氏,但名字需要与姓氏不同。并假设此计算需要 1 秒。
模板
<form [formGroup]="personForm">
<div>
<input type="text" name="firstName" formControlName="firstName" placeholder="First Name" />
</div>
<div>
<input type="text" name="lastName" formControlName="lastName" placeholder="Last Name" />
</div>
<p style="color: red" *ngIf="personForm.errors?.sameValue">First name and last name should not be the same.</p>
<button type="submit">Submit</button>
</form>
组件
下面的validateBusiness
验证函数将return一个Promise
:
import { Component, OnInit } from '@angular/core';
import {AbstractControl, FormBuilder, FormGroup, ValidationErrors, Validators} from "@angular/forms";
import {Observable} from "rxjs/Observable";
import "rxjs/add/operator/delay";
import "rxjs/add/operator/map";
import "rxjs/add/observable/from";
@Component({
selector: 'app-async-validation',
templateUrl: './async-validation.component.html',
styleUrls: ['./async-validation.component.css']
})
export class AsyncValidationComponent implements OnInit {
personForm: FormGroup;
constructor(private _formBuilder: FormBuilder) { }
ngOnInit() {
this.personForm = this._formBuilder.group({
firstName: [ '', Validators.required ],
lastName: [ '', Validators.required ],
}, {
asyncValidator: this.validateBusiness.bind(this)
});
}
validateBusiness(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (control.value.firstName !== control.value.lastName) {
resolve(null);
}
else {
resolve({sameValue: 'ERROR...'});
}
},
1000);
});
}
}
或者,验证函数可以 return 一个 Observable
:
validateBusiness(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return Observable
.from([control.value.firstName !== control.value.lastName])
.map(valid => valid ? null : {sameValue: 'ERROR...'})
.delay(1000);
}
解决方案 2 - 编排多个控件的验证错误
另一种选择是在表单更改时手动验证,然后将结果传递给一个可观察对象,稍后可以由 FormGroup
和 FormControl
异步验证器使用。
我创建了一个POC here。
IValidationResponse
用于验证表单数据的验证服务的响应。
import {IValidationErrorDescription} from "./IValidationErrorDescription";
export interface IValidationResponse {
validations: IValidationErrorDescription[];
}
IValidationErrorDescription
验证响应错误说明。
export interface IValidationErrorDescription {
display: string;
code: string;
fields: string[];
}
业务验证服务
验证服务,实现表单数据验证业务。
import { Injectable } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/map';
import {IValidationResponse} from "../model/IValidationResponse";
@Injectable()
export class BusinessValidationService {
public validateForm(value: any): Observable<IValidationResponse> {
return Observable
.from([value.firstName !== value.lastName])
.map(valid => valid ?
{validations: []}
:
{
validations: [
{
code: 'sameValue',
display: 'First name and last name are the same',
fields: ['firstName', 'lastName']
}
]
}
)
.delay(500);
}
}
FormValidationService
验证服务,用于为 FormGroup
和 FormControl
构建异步验证器并订阅表单数据的更改,以便将验证委托给验证回调(例如:BusinessValidationService
).
它提供了以下内容:
validateFormOnChange()
- 当表单更改时它调用验证回调 validateFormCallback
并且当它使用 control.validateFormGroup()
触发 FormGroup
和 FormControl
的验证时.
createGroupAsyncValidator()
- 为 FormGroup
创建一个异步验证器
createControlAsyncValidator()
- 为 FormControl
创建一个异步验证器
代码:
import { Injectable } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/first';
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/debounceTime';
import {AbstractControl, AsyncValidatorFn, FormGroup} from '@angular/forms';
import {ReplaySubject} from 'rxjs/ReplaySubject';
import {IValidationResponse} from "../model/IValidationResponse";
@Injectable()
export class FormValidationService {
private _subject$ = new ReplaySubject<IValidationResponse>(1);
private _validationResponse$ = this._subject$.debounceTime(100).share();
private _oldValue = null;
constructor() {
this._subject$.subscribe();
}
public get onValidate(): Observable<IValidationResponse> {
return this._subject$.map(response => response);
}
public validateFormOnChange(group: FormGroup, validateFormCallback: (value: any) => Observable<IValidationResponse>) {
group.valueChanges.subscribe(value => {
const isChanged = this.isChanged(value, this._oldValue);
this._oldValue = value;
if (!isChanged) {
return;
}
this._subject$.next({validations: []});
this.validateFormGroup(group);
validateFormCallback(value).subscribe(validationRes => {
this._subject$.next(validationRes);
this.validateFormGroup(group);
});
});
}
private isChanged(newValue, oldValue): boolean {
if (!newValue) {
return true;
}
return !!Object.keys(newValue).find(key => !oldValue || newValue[key] !== oldValue[key]);
}
private validateFormGroup(group: FormGroup) {
group.updateValueAndValidity({ emitEvent: true, onlySelf: false });
Object.keys(group.controls).forEach(controlName => {
group.controls[controlName].updateValueAndValidity({ emitEvent: true, onlySelf: false });
});
}
public createControlAsyncValidator(fieldName: string): AsyncValidatorFn {
return (control: AbstractControl) => {
return this._validationResponse$
.switchMap(validationRes => {
const errors = validationRes.validations
.filter(validation => validation.fields.indexOf(fieldName) >= 0)
.reduce((errorMap, validation) => {
errorMap[validation.code] = validation.display;
return errorMap;
}, {});
return Observable.from([errors]);
})
.first();
};
}
public createGroupAsyncValidator(): AsyncValidatorFn {
return (control: AbstractControl) => {
return this._validationResponse$
.switchMap(validationRes => {
const errors = validationRes.validations
.reduce((errorMap, validation) => {
errorMap[validation.code] = validation.display;
return errorMap;
}, {});
return Observable.from([errors]);
})
.first();
};
}
}
AsyncFormValidateComponent 模板
定义firstName
和lastName
FormControl
,它们在personForm
FormGroup
中。对于此示例,条件是 firstName
和 lastName
应该不同。
<form [formGroup]="personForm">
<div>
<label for="firstName">First name:</label>
<input type="text"
id="firstName"
name="firstName"
formControlName="firstName"
placeholder="First Name" />
<span *ngIf="personForm.controls['firstName'].errors?.sameValue">Same as last name</span>
</div>
<div>
<label for="lastName">Last name:</label>
<input type="text"
id="lastName"
name="lastName"
formControlName="lastName"
placeholder="Last Name" />
<span *ngIf="personForm.controls['lastName'].errors?.sameValue">Same as first name</span>
</div>
<p style="color: red" *ngIf="personForm.errors?.sameValue">First name and last name should not be the same.</p>
<button type="submit">Submit</button>
</form>
AsyncValidateFormComponent
以组件为例,使用FrmValidationService
实现验证。由于 providers: [FormValidationService]
,此组件有自己的此服务实例。由于 Angular 分层注入器特性,一个注入器将与该组件相关联,并且将为该服务的每个实例创建一个实例 AsyncValidateFormComponent
。因此能够以每个组件实例为基础跟踪此服务内的验证状态。
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import 'rxjs/add/operator/delay';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/from';
import {FormValidationService} from "../services/form-validation.service";
import {BusinessValidationService} from "../services/business-validation.service";
@Component({
selector: 'app-async-validate-form',
templateUrl: './async-validate-form.component.html',
styleUrls: ['./async-validate-form.component.css'],
providers: [FormValidationService]
})
export class AsyncValidateFormComponent implements OnInit {
personForm: FormGroup;
constructor(private _formBuilder: FormBuilder,
private _formValidationService: FormValidationService,
private _businessValidationService: BusinessValidationService) {
}
ngOnInit() {
this.personForm = this._formBuilder.group({
firstName: ['', Validators.required, this._formValidationService.createControlAsyncValidator('firstName')],
lastName: ['', Validators.required, this._formValidationService.createControlAsyncValidator('lastName')],
}, {
asyncValidator: this._formValidationService.createGroupAsyncValidator()
});
this._formValidationService.validateFormOnChange(this.personForm, value => this._businessValidationService.validateForm(value));
}
}
AppModule
它使用 ReactiveFormsModule
以便与 FormBuilder
、FormGroup
和 FormControl
一起工作。还提供了BusinessValidationService
.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { AsyncValidateFormComponent } from './async-validate-form/async-validate-form.component';
import {BusinessValidationService} from "./services/business-validation.service";
@NgModule({
declarations: [
AppComponent,
AsyncValidateFormComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule
],
providers: [
BusinessValidationService
],
bootstrap: [AppComponent]
})
export class AppModule { }
我正在尝试实现异步验证器但没有成功...
我的组件创建了一个表单:
this.personForm = this._frmBldr.group({
lastname: [ '', Validators.compose([Validators.required, Validators.minLength(2) ]) ],
firstname: [ '', Validators.compose([Validators.required, Validators.minLength(2) ]) ],
birthdate: [ '', Validators.compose([ Validators.required, DateValidators.checkIsNotInTheFuture ]) ],
driverLicenceDate: [ '', Validators.compose([ Validators.required, DateValidators.checkIsNotInTheFuture ]), this.asyncValidationLicenceDate.bind(this) ],
}, {
asyncValidator: this.validateBusiness.bind(this),
validator: this.validateDriverLicenseOlderThanBirthdate,
});
我的验证方法
validateBusiness(group: FormGroup) {
console.log('validateBusiness')
return this._frmService
.validateForm(group.value)
.map((validationResponse: IValidationResponse) => {
if (validationResponse) {
validationResponse.validations.forEach( (validationError: IValidationErrorDescription) => {
let errorMsg = validationError.display;
let errorCode = validationError.code;
validationError.fields.forEach( (fieldName: string) => {
console.log(fieldName);
let control = this.personForm.controls[fieldName];
let existingErrors = control.errors || {};
existingErrors[errorCode] = errorMsg;
control.setErrors(existingErrors);
});
});
}
});
}
所有验证都被成功调用,除了从未调用过的 validateBusiness 方法(在 formbuilder.group
的 extra.asyncValidator
参数中)...有人可以告诉我我做错了什么吗?
发送
TL;DR: 通过分析您的用例,您可能需要解决方案 2
问题
问题在于异步验证器的定义和使用方式。
异步验证器定义为:
export interface AsyncValidatorFn {
(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
}
这是因为 FormBuilder.group()
实际上是在调用 FormGroup
构造函数:
constructor(controls: {
[key: string]: AbstractControl;
}, validator?: ValidatorFn | null, asyncValidator?: AsyncValidatorFn | null);
因此,异步验证器函数将接收一个 AbstractControl
实例,在本例中为 FormGroup
实例,因为验证器位于 FormGroup
级别。验证器需要 return Promise
或 ValidationErrors
的 Observable
,如果不存在验证错误则为 null。
ValidationErrors
被定义为字符串键和值(任何你喜欢的)的映射。键实际上是定义验证错误类型的字符串(例如:"required")。
export declare type ValidationErrors = {
[key: string]: any;
};
AbstractControl.setErrors()?
- 在您的示例中,您定义的函数不 return 任何东西,但实际上直接更改控制错误。调用 setErrors
仅适用于手动调用验证并因此仅手动设置错误的情况。相反,在您的示例中,方法是混合的,FormControl
s 附加了验证函数,它将自动 运行,FormGroup
异步验证函数,运行s 也自动尝试设置错误,从而手动设置有效性。这行不通。
您需要采用以下两种方法之一:
- 附加验证函数,它将 运行 自动设置错误和有效性。不要尝试在附加了验证功能的控件上手动设置任何内容。
- 手动设置错误和有效性,而不将任何验证函数附加到受影响的
AbstractControl
个实例。
如果你想保持一切干净,那么你可以继续实现单独的验证功能。 FormControl
验证将只处理一个控件。 FormGroup
验证会将表单组的多个方面视为一个整体。
如果您想使用验证服务,它实际上会验证整个表单,就像您所做的那样,然后将每个错误委托给每个适当的控件验证器,那么您可以使用解决方案 2.这个有点难。
但是如果您同意在 FormGroup
级别使用验证服务的验证器,那么可以使用 解决方案 1.[=73 来实现=]
解决方案 1 - 在 FormGroup 级别创建错误
假设我们要输入名字和姓氏,但名字需要与姓氏不同。并假设此计算需要 1 秒。
模板
<form [formGroup]="personForm">
<div>
<input type="text" name="firstName" formControlName="firstName" placeholder="First Name" />
</div>
<div>
<input type="text" name="lastName" formControlName="lastName" placeholder="Last Name" />
</div>
<p style="color: red" *ngIf="personForm.errors?.sameValue">First name and last name should not be the same.</p>
<button type="submit">Submit</button>
</form>
组件
下面的validateBusiness
验证函数将return一个Promise
:
import { Component, OnInit } from '@angular/core';
import {AbstractControl, FormBuilder, FormGroup, ValidationErrors, Validators} from "@angular/forms";
import {Observable} from "rxjs/Observable";
import "rxjs/add/operator/delay";
import "rxjs/add/operator/map";
import "rxjs/add/observable/from";
@Component({
selector: 'app-async-validation',
templateUrl: './async-validation.component.html',
styleUrls: ['./async-validation.component.css']
})
export class AsyncValidationComponent implements OnInit {
personForm: FormGroup;
constructor(private _formBuilder: FormBuilder) { }
ngOnInit() {
this.personForm = this._formBuilder.group({
firstName: [ '', Validators.required ],
lastName: [ '', Validators.required ],
}, {
asyncValidator: this.validateBusiness.bind(this)
});
}
validateBusiness(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (control.value.firstName !== control.value.lastName) {
resolve(null);
}
else {
resolve({sameValue: 'ERROR...'});
}
},
1000);
});
}
}
或者,验证函数可以 return 一个 Observable
:
validateBusiness(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return Observable
.from([control.value.firstName !== control.value.lastName])
.map(valid => valid ? null : {sameValue: 'ERROR...'})
.delay(1000);
}
解决方案 2 - 编排多个控件的验证错误
另一种选择是在表单更改时手动验证,然后将结果传递给一个可观察对象,稍后可以由 FormGroup
和 FormControl
异步验证器使用。
我创建了一个POC here。
IValidationResponse
用于验证表单数据的验证服务的响应。
import {IValidationErrorDescription} from "./IValidationErrorDescription";
export interface IValidationResponse {
validations: IValidationErrorDescription[];
}
IValidationErrorDescription
验证响应错误说明。
export interface IValidationErrorDescription {
display: string;
code: string;
fields: string[];
}
业务验证服务
验证服务,实现表单数据验证业务。
import { Injectable } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/map';
import {IValidationResponse} from "../model/IValidationResponse";
@Injectable()
export class BusinessValidationService {
public validateForm(value: any): Observable<IValidationResponse> {
return Observable
.from([value.firstName !== value.lastName])
.map(valid => valid ?
{validations: []}
:
{
validations: [
{
code: 'sameValue',
display: 'First name and last name are the same',
fields: ['firstName', 'lastName']
}
]
}
)
.delay(500);
}
}
FormValidationService
验证服务,用于为 FormGroup
和 FormControl
构建异步验证器并订阅表单数据的更改,以便将验证委托给验证回调(例如:BusinessValidationService
).
它提供了以下内容:
validateFormOnChange()
- 当表单更改时它调用验证回调validateFormCallback
并且当它使用control.validateFormGroup()
触发FormGroup
和FormControl
的验证时.createGroupAsyncValidator()
- 为FormGroup
创建一个异步验证器
createControlAsyncValidator()
- 为FormControl
创建一个异步验证器
代码:
import { Injectable } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/first';
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/debounceTime';
import {AbstractControl, AsyncValidatorFn, FormGroup} from '@angular/forms';
import {ReplaySubject} from 'rxjs/ReplaySubject';
import {IValidationResponse} from "../model/IValidationResponse";
@Injectable()
export class FormValidationService {
private _subject$ = new ReplaySubject<IValidationResponse>(1);
private _validationResponse$ = this._subject$.debounceTime(100).share();
private _oldValue = null;
constructor() {
this._subject$.subscribe();
}
public get onValidate(): Observable<IValidationResponse> {
return this._subject$.map(response => response);
}
public validateFormOnChange(group: FormGroup, validateFormCallback: (value: any) => Observable<IValidationResponse>) {
group.valueChanges.subscribe(value => {
const isChanged = this.isChanged(value, this._oldValue);
this._oldValue = value;
if (!isChanged) {
return;
}
this._subject$.next({validations: []});
this.validateFormGroup(group);
validateFormCallback(value).subscribe(validationRes => {
this._subject$.next(validationRes);
this.validateFormGroup(group);
});
});
}
private isChanged(newValue, oldValue): boolean {
if (!newValue) {
return true;
}
return !!Object.keys(newValue).find(key => !oldValue || newValue[key] !== oldValue[key]);
}
private validateFormGroup(group: FormGroup) {
group.updateValueAndValidity({ emitEvent: true, onlySelf: false });
Object.keys(group.controls).forEach(controlName => {
group.controls[controlName].updateValueAndValidity({ emitEvent: true, onlySelf: false });
});
}
public createControlAsyncValidator(fieldName: string): AsyncValidatorFn {
return (control: AbstractControl) => {
return this._validationResponse$
.switchMap(validationRes => {
const errors = validationRes.validations
.filter(validation => validation.fields.indexOf(fieldName) >= 0)
.reduce((errorMap, validation) => {
errorMap[validation.code] = validation.display;
return errorMap;
}, {});
return Observable.from([errors]);
})
.first();
};
}
public createGroupAsyncValidator(): AsyncValidatorFn {
return (control: AbstractControl) => {
return this._validationResponse$
.switchMap(validationRes => {
const errors = validationRes.validations
.reduce((errorMap, validation) => {
errorMap[validation.code] = validation.display;
return errorMap;
}, {});
return Observable.from([errors]);
})
.first();
};
}
}
AsyncFormValidateComponent 模板
定义firstName
和lastName
FormControl
,它们在personForm
FormGroup
中。对于此示例,条件是 firstName
和 lastName
应该不同。
<form [formGroup]="personForm">
<div>
<label for="firstName">First name:</label>
<input type="text"
id="firstName"
name="firstName"
formControlName="firstName"
placeholder="First Name" />
<span *ngIf="personForm.controls['firstName'].errors?.sameValue">Same as last name</span>
</div>
<div>
<label for="lastName">Last name:</label>
<input type="text"
id="lastName"
name="lastName"
formControlName="lastName"
placeholder="Last Name" />
<span *ngIf="personForm.controls['lastName'].errors?.sameValue">Same as first name</span>
</div>
<p style="color: red" *ngIf="personForm.errors?.sameValue">First name and last name should not be the same.</p>
<button type="submit">Submit</button>
</form>
AsyncValidateFormComponent
以组件为例,使用FrmValidationService
实现验证。由于 providers: [FormValidationService]
,此组件有自己的此服务实例。由于 Angular 分层注入器特性,一个注入器将与该组件相关联,并且将为该服务的每个实例创建一个实例 AsyncValidateFormComponent
。因此能够以每个组件实例为基础跟踪此服务内的验证状态。
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import 'rxjs/add/operator/delay';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/from';
import {FormValidationService} from "../services/form-validation.service";
import {BusinessValidationService} from "../services/business-validation.service";
@Component({
selector: 'app-async-validate-form',
templateUrl: './async-validate-form.component.html',
styleUrls: ['./async-validate-form.component.css'],
providers: [FormValidationService]
})
export class AsyncValidateFormComponent implements OnInit {
personForm: FormGroup;
constructor(private _formBuilder: FormBuilder,
private _formValidationService: FormValidationService,
private _businessValidationService: BusinessValidationService) {
}
ngOnInit() {
this.personForm = this._formBuilder.group({
firstName: ['', Validators.required, this._formValidationService.createControlAsyncValidator('firstName')],
lastName: ['', Validators.required, this._formValidationService.createControlAsyncValidator('lastName')],
}, {
asyncValidator: this._formValidationService.createGroupAsyncValidator()
});
this._formValidationService.validateFormOnChange(this.personForm, value => this._businessValidationService.validateForm(value));
}
}
AppModule
它使用 ReactiveFormsModule
以便与 FormBuilder
、FormGroup
和 FormControl
一起工作。还提供了BusinessValidationService
.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { AsyncValidateFormComponent } from './async-validate-form/async-validate-form.component';
import {BusinessValidationService} from "./services/business-validation.service";
@NgModule({
declarations: [
AppComponent,
AsyncValidateFormComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule
],
providers: [
BusinessValidationService
],
bootstrap: [AppComponent]
})
export class AppModule { }