dan*_*man 9 javascript validation typescript angular-material2 angular
我正在使用最新的Angular和最新的Angular Material.我有一个datepicker,我想添加一些验证.文档说该required属性应该开箱即用,但它似乎不像其他表单元素那样处理错误.
这是我的加价:
<mat-form-field class="full-width">
<input matInput [matDatepicker]="dob" placeholder="Date of birth" [(ngModel)]="myService.request.dob" #dob="ngModel" required app-validateAdult>
<mat-datepicker-toggle matSuffix [for]="dob"></mat-datepicker-toggle>
<mat-datepicker #dob></mat-datepicker>
<mat-error *ngIf="dob.errors && dob.errors.required">Your date of birth is required</mat-error>
</mat-form-field>
Run Code Online (Sandbox Code Playgroud)
这适用于happy-path,因此当选择日期时,日期最终会出现在期望的属性中myService.
然而,验证并不像我期望的那样有效; 在这种情况下,如果我在没有输入日期的情况下单击该字段然后退出该字段,则输入会获得红色样式,但通常的[controlName].errors对象不会被填充.这意味着以通常的方式显示错误消息(与同一页面上不是日期选择器的其他输入一起使用的方式)不起作用:
<mat-error *ngIf="dob.errors && dob.errors.required">Your date of birth is required</mat-error>
Run Code Online (Sandbox Code Playgroud)
在*ngIf因为日期选择器似乎从来没有更新是不正确的dob.errors,这样就不会显示错误消息,即使输入的样式为无效.
这是正确的吗?我错过了什么吗?
我还尝试添加一个自定义指令来验证使用datepicker选择的日期表明用户已超过18:
export class AdultValidator implements Validator {
constructor(
@Attribute('app-validateAdult') public validateAdult: string
) { }
validate(control: AbstractControl): { [key: string]: any } {
const dob = control.value;
const today = moment().startOf('day');
const delta = today.diff(dob, 'years', false);
if (delta <= 18) {
return {
validateAdult: {
'requiredAge': '18+',
'currentAge': delta
}
};
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我正在尝试使用类似的matError(除了链接dob.errors.validateAdult而不是)在适当时显示错误.
有趣的是,如果我选择一个不到18年前的日期,整个输入,标签等,将获得默认的红色错误样式,所以发生了一些事情,但我仍然没有看到我的错误消息.
我们欢迎所有的建议!
确切版本:
Angular CLI: 1.6.3
Node: 6.11.0
OS: win32 x64
Angular: 5.1.3
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router
@angular/cdk: 5.0.4
@angular/cli: 1.6.3
@angular/flex-layout: 2.0.0-beta.12
@angular/material-moment-adapter: 5.0.4
@angular/material: 5.0.4
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.3
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.4.2
webpack: 3.10.0
Run Code Online (Sandbox Code Playgroud)
我设法在不使用 的情况下完成了这项工作ErrorStateMatcher,尽管这确实帮助我找到了解决方案。离开这里以供将来参考或帮助他人。
我将表单转换为反应式表单而不是模板驱动的表单,并将自定义验证器指令更改为更简单的验证器(非基于指令)。
这是工作代码:
我的form.component.html:
<div class="container" fxlayoutgap="16px" fxlayout fxlayout.xs="column" fxlayout.sm="column" *ngIf="fieldset.controls[control].type === 'datepicker'">
<mat-form-field class="full-width" fxflex>
<input matInput
[formControlName]="control"
[matDatepicker]="dob"
[placeholder]="fieldset.controls[control].label"
[max]="fieldset.controls[control].validation.max">
<mat-datepicker-toggle matSuffix [for]="dob"></mat-datepicker-toggle>
<mat-datepicker #dob></mat-datepicker>
<mat-error *ngIf="myForm.get(control).hasError('required')">
{{fieldset.controls[control].validationMessages.required}}</mat-error>
<mat-error *ngIf="myForm.get(control).hasError('underEighteen')">
{{fieldset.controls[control].validationMessages.underEighteen}}
</mat-error>
</mat-form-field>
</div>
Run Code Online (Sandbox Code Playgroud)
注意:上面的代码位于几个ngFor定义fieldsetand值的嵌套循环中control。在这个例子中control映射到字符串dob。
over-teen.validator.ts:
import { ValidatorFn, AbstractControl } from '@angular/forms';
import * as moment from 'moment';
export function overEighteen(): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
const dob = control.value;
const today = moment().startOf('day');
const delta = today.diff(dob, 'years', false);
if (delta <= 18) {
return {
underEighteen: {
'requiredAge': '18+',
'currentAge': delta
}
};
}
return null;
};
}
Run Code Online (Sandbox Code Playgroud)
我的form.component.ts:
buildForm(): void {
const formObject = {};
this.myService.request.fieldsets.forEach((controlsGroup, index) => {
this.fieldsets.push({
controlNames: Object.keys(controlsGroup.controls)
});
for (const control in controlsGroup.controls) {
if (controlsGroup.controls.hasOwnProperty(control)) {
const controlData = controlsGroup.controls[control];
const controlAttributes = [controlData.value];
const validators = [];
if (controlData.validation) {
for (const validator in controlData.validation) {
if (controlData.validation.hasOwnProperty(validator)) {
if (validator === 'overEighteenValidator') {
validators.push(this.overEighteenValidator);
} else {
validators.push(Validators[validator]);
}
}
}
controlAttributes.push(Validators.compose(validators));
}
formObject[control] = controlAttributes;
}
}
});
this.myForm = this.fb.group(formObject);
}
Run Code Online (Sandbox Code Playgroud)
我在Angular Material Forms中使用ErrorStateMatcher,它运行完美。
您应该具有如下代码:
<mat-form-field class="full-width">
<input matInput [matDatepicker]="dob" placeholder="Date of birth" formControlName="dob" required app-validateAdult>
<mat-datepicker-toggle matSuffix [for]="dob"></mat-datepicker-toggle>
<mat-datepicker #dob></mat-datepicker>
<mat-error *ngIf="dob.hasError('required')">Your date of birth is required</mat-error>
</mat-form-field>
Run Code Online (Sandbox Code Playgroud)
和打字稿:
import { ErrorStateMatcher } from '@angular/material/core';
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(
control: FormControl | null,
form: FormGroupDirective | NgForm | null
): boolean {
const isSubmitted = form && form.submitted;
return !!(
control &&
control.invalid &&
(control.dirty || control.touched || isSubmitted)
);
}
}
export class AdultValidator implements Validator {
dob = new FormControl('', [
Validators.required
]);
matcher = new MyErrorStateMatcher();
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处查看有关它的更多信息:https : //material.angular.io/components/input/overview
| 归档时间: |
|
| 查看次数: |
23976 次 |
| 最近记录: |