Angular 中的自定义验证未显示验证错误消息 2
Validation Error Message not getting displayed for custom validation in Angular 2
我有一张注册表,用户需要在其中提供用户名。当客户输入用户名时,如果该用户名已存在于数据库中,我想显示验证错误消息。
register.html
<-- code here-->
<div class="form-group">
<label for="username" class="col-sm-3 control-label">UserName</label>
<div class=" col-sm-6">
<input type="text" ngControl="userName" maxlength="45" class="form-control" [(ngModel)]="parent.userName" placeholder="UserName" #userName="ngForm" required data-is-unique/>
<validation-message control="userName"></validation-message>
</div>
</div>
<--code here-->
register.component.ts
import {Component} from 'angular2/core';
import {NgForm, FormBuilder, Validators, FORM_DIRECTIVES} from 'angular2/common';
import {ValidationService} from '../services/validation.service';
import {ValidationMessages} from './validation-messages.component';
@Component({
selector: 'register',
templateUrl: './views/register.html',
directives: [ROUTER_DIRECTIVES, ValidationMessages, FORM_DIRECTIVES],
providers: []
})
export class ParentSignUpComponent {
parentSignUpForm: any;
constructor(private _formBuilder: FormBuilder) {
this._stateService.isAuthenticatedEvent.subscribe(value => {
this.onAuthenticationEvent(value);
});
this.parent = new ParentSignUpModel();
this.parentSignUpForm = this._formBuilder.group({
'firstName': ['', Validators.compose([Validators.required, Validators.maxLength(45), ValidationService.nameValidator])],
'middleName': ['', Validators.compose([Validators.maxLength(45), ValidationService.nameValidator])],
'lastName': ['', Validators.compose([Validators.required, Validators.maxLength(45), ValidationService.nameValidator])],
'userName': ['', Validators.compose([Validators.required, ValidationService.checkUserName])]
});
}
}
验证-message.component
import {Component, Host} from 'angular2/core';
import {NgFormModel} from 'angular2/common';
import {ValidationService} from '../services/validation.service';
@Component({
selector: 'validation-message',
inputs: ['validationName: control'],
template: `<div *ngIf="errorMessage !== null" class="error-message"> {{errorMessage}}</div>`
})
export class ValidationMessages {
private validationName: string;
constructor (@Host() private _formDir: NgFormModel) {}
get errorMessage() {
let control = this._formDir.form.find(this.validationName);
for (let propertyName in control.errors) {
if (control.errors.hasOwnProperty(propertyName) && control.touched) {
return ValidationService.getValidatorErrorMessage(propertyName);
}
}
return null;
}
}
验证-service.ts
import {Injectable, Injector} from 'angular2/core';
import {Control} from 'angular2/common';
import {Observable} from 'rxjs/Observable';
import {Http, Response, HTTP_PROVIDERS} from 'angular2/http';
import 'rxjs/Rx';
interface ValidationResult {
[key:string]:boolean;
}
@Injectable()
export class ValidationService {
static getValidatorErrorMessage(code: string) {
let config = {
'required': 'This field is required!',
'maxLength': 'Field is too long!',
'invalidName': 'This field can contain only alphabets, space, dot, hyphen, and apostrophe.',
'userAlreadyInUse': 'UserName selected already in use! Please try another.'
};
return config[code];
}
static checkUserName(control: Control): Promise<ValidationResult> {
let injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
let http = injector.get(Http);
let alreadyExists: boolean;
if (control.value) {
return new Promise((resolve, reject) => {
setTimeout(() => {
http.get('/isUserNameUnique/' + control.value).map(response => response.json()).subscribe(result => {
if (result === false) {
resolve({'userAlreadyInUse': true});
} else {
resolve(null);
}
});
}, 1000);
});
}
}
}
现在,当我 运行 并提供数据库中已存在的用户名时,我得到的 'result' 变量的值为 false,这是预期的且正确的。但未显示验证错误消息。我能够 运行 并获取其他自定义验证函数的验证错误消息。我正在使用 Angular 2.0.0-beta.15。有人可以帮助我了解可能是什么问题吗?
异步验证存在一些已知问题
- https://github.com/angular/angular/issues/1068
- https://github.com/angular/angular/issues/7538
- https://github.com/angular/angular/issues/8118
- https://github.com/angular/angular/issues/8923
- https://github.com/angular/angular/issues/8022
这段代码可以简化
return new Promise((resolve, reject) => {
setTimeout(() => {
http.get('/isUserNameUnique/' + control.value).map(response => response.json())
.subscribe(result => {
if (result === false) {
resolve({'userAlreadyInUse': true});
} else {
resolve(null);
}
});
}, 1000);
});
至
return http.get('/isUserNameUnique/' + control.value).map(response => response.json())
.timeout(200, new Error('Timeout has occurred.'));
.map(result => {
if (result === false) {
resolve({'userAlreadyInUse': true});
} else {
resolve(null);
}
}).toPromise();
不要忘记导入 map
、timeout
和 toPromise
。
如果您在调用方站点上使用 subscribe()
而不是 then()
,那么您可以事件省略 toPromise()
如果你调查这个 -
'userName': ['', Validators.compose([Validators.required, ValidationService.checkUserName])] });
-- 你可以看到我同时使用了同步和异步验证。当我将 checkUserName 的方法更改为 'Validators.composeAsync(ValidationService.checkUserName)'
而不是 Validators.compose
方法时,显示了错误消息。
我有一张注册表,用户需要在其中提供用户名。当客户输入用户名时,如果该用户名已存在于数据库中,我想显示验证错误消息。
register.html
<-- code here-->
<div class="form-group">
<label for="username" class="col-sm-3 control-label">UserName</label>
<div class=" col-sm-6">
<input type="text" ngControl="userName" maxlength="45" class="form-control" [(ngModel)]="parent.userName" placeholder="UserName" #userName="ngForm" required data-is-unique/>
<validation-message control="userName"></validation-message>
</div>
</div>
<--code here-->
register.component.ts
import {Component} from 'angular2/core';
import {NgForm, FormBuilder, Validators, FORM_DIRECTIVES} from 'angular2/common';
import {ValidationService} from '../services/validation.service';
import {ValidationMessages} from './validation-messages.component';
@Component({
selector: 'register',
templateUrl: './views/register.html',
directives: [ROUTER_DIRECTIVES, ValidationMessages, FORM_DIRECTIVES],
providers: []
})
export class ParentSignUpComponent {
parentSignUpForm: any;
constructor(private _formBuilder: FormBuilder) {
this._stateService.isAuthenticatedEvent.subscribe(value => {
this.onAuthenticationEvent(value);
});
this.parent = new ParentSignUpModel();
this.parentSignUpForm = this._formBuilder.group({
'firstName': ['', Validators.compose([Validators.required, Validators.maxLength(45), ValidationService.nameValidator])],
'middleName': ['', Validators.compose([Validators.maxLength(45), ValidationService.nameValidator])],
'lastName': ['', Validators.compose([Validators.required, Validators.maxLength(45), ValidationService.nameValidator])],
'userName': ['', Validators.compose([Validators.required, ValidationService.checkUserName])]
});
}
}
验证-message.component
import {Component, Host} from 'angular2/core';
import {NgFormModel} from 'angular2/common';
import {ValidationService} from '../services/validation.service';
@Component({
selector: 'validation-message',
inputs: ['validationName: control'],
template: `<div *ngIf="errorMessage !== null" class="error-message"> {{errorMessage}}</div>`
})
export class ValidationMessages {
private validationName: string;
constructor (@Host() private _formDir: NgFormModel) {}
get errorMessage() {
let control = this._formDir.form.find(this.validationName);
for (let propertyName in control.errors) {
if (control.errors.hasOwnProperty(propertyName) && control.touched) {
return ValidationService.getValidatorErrorMessage(propertyName);
}
}
return null;
}
}
验证-service.ts
import {Injectable, Injector} from 'angular2/core';
import {Control} from 'angular2/common';
import {Observable} from 'rxjs/Observable';
import {Http, Response, HTTP_PROVIDERS} from 'angular2/http';
import 'rxjs/Rx';
interface ValidationResult {
[key:string]:boolean;
}
@Injectable()
export class ValidationService {
static getValidatorErrorMessage(code: string) {
let config = {
'required': 'This field is required!',
'maxLength': 'Field is too long!',
'invalidName': 'This field can contain only alphabets, space, dot, hyphen, and apostrophe.',
'userAlreadyInUse': 'UserName selected already in use! Please try another.'
};
return config[code];
}
static checkUserName(control: Control): Promise<ValidationResult> {
let injector = Injector.resolveAndCreate([HTTP_PROVIDERS]);
let http = injector.get(Http);
let alreadyExists: boolean;
if (control.value) {
return new Promise((resolve, reject) => {
setTimeout(() => {
http.get('/isUserNameUnique/' + control.value).map(response => response.json()).subscribe(result => {
if (result === false) {
resolve({'userAlreadyInUse': true});
} else {
resolve(null);
}
});
}, 1000);
});
}
}
}
现在,当我 运行 并提供数据库中已存在的用户名时,我得到的 'result' 变量的值为 false,这是预期的且正确的。但未显示验证错误消息。我能够 运行 并获取其他自定义验证函数的验证错误消息。我正在使用 Angular 2.0.0-beta.15。有人可以帮助我了解可能是什么问题吗?
异步验证存在一些已知问题
- https://github.com/angular/angular/issues/1068
- https://github.com/angular/angular/issues/7538
- https://github.com/angular/angular/issues/8118
- https://github.com/angular/angular/issues/8923
- https://github.com/angular/angular/issues/8022
这段代码可以简化
return new Promise((resolve, reject) => {
setTimeout(() => {
http.get('/isUserNameUnique/' + control.value).map(response => response.json())
.subscribe(result => {
if (result === false) {
resolve({'userAlreadyInUse': true});
} else {
resolve(null);
}
});
}, 1000);
});
至
return http.get('/isUserNameUnique/' + control.value).map(response => response.json())
.timeout(200, new Error('Timeout has occurred.'));
.map(result => {
if (result === false) {
resolve({'userAlreadyInUse': true});
} else {
resolve(null);
}
}).toPromise();
不要忘记导入 map
、timeout
和 toPromise
。
如果您在调用方站点上使用 subscribe()
而不是 then()
,那么您可以事件省略 toPromise()
如果你调查这个 -
'userName': ['', Validators.compose([Validators.required, ValidationService.checkUserName])] });
-- 你可以看到我同时使用了同步和异步验证。当我将 checkUserName 的方法更改为 'Validators.composeAsync(ValidationService.checkUserName)'
而不是 Validators.compose
方法时,显示了错误消息。