我的模型驱动表单中有一个自定义验证器,用于验证。
模板 -
<form [formGroup] = "myForm" (ngSubmit) = "save(myForm.value)">
<div>
<label>Name</label>
<input type="text" formControlName="name">
</div>
<p *ngIf="myForm.controls.name?.errors">This has to be rahulsingh!</p>
<button type = "submit" > Submit</button>
</form>
组件 -
this.myForm = this.fb.group({
name: ['', [this.validateName]]
});
validateName(c: FormControl) {
return (c.value === 'rahulSingh') ? null : {
notCorrect: true
};
}
这适用于模型驱动表单
但是如何对模板驱动使用相同的验证功能
我正在关注此链接http://blog.thoughtram.io/angular/2016/03/21/template-driven-forms-in-angular-2.html
但我无法理解如何使这两个表单的函数全局并将其用作指令。我总是在尝试实现这一目标时遇到了一个奇怪的错误。
当我尝试做
时,我的模板中还有一个奇怪的事情<p *ngIf="myForm.hasErrors('notCorrect')">This has to be rahulsingh!</p>
我得到无法读取属性&#39; hasError&#39;未定义的。
答案 0 :(得分:3)
首先,我们将构建适用于模板驱动表单的指令,该指令将自动使其适用于Reactive表单(整洁的技巧):
import { Directive, Input } from '@angular/core';
import { FormControl, NG_VALIDATORS, Validator } from '@angular/forms';
@Directive({
selector: '[requiredName][ngModel]',
providers: [{provide: NG_VALIDATORS, useExisting: SpecificNameValidatorDirective, multi: true}]
})
export class SpecificNameValidatorDirective implements Validator {
private valFn = (c: FormControl, name: string) {
return (c.value === name) ? null : {
notCorrect: true
};
}
@Input('requiredName') name: string = "temp";
constructor() {
}
validate(control: AbstractControl): {[key: string]: any} {
console.log("validation station", this.name, control.value);
return this.valFn(control, this.name);
}
}
这里有一个转折,因为名称不是硬编码的,虽然提供了默认值,这意味着我们可以像模板驱动形式一样使用该指令:
<form #myForm="ngForm" (ngSubmit)="save(myForm.value)">
<div>
<label>Name</label>
<input requiredName="rahulSingh" name="name" ngModel #name="ngModel" type="text" id="name">
</div>
<p *ngIf="name.errors?.notCorrect">This has to be rahulSingh!</p>
<button type="submit"> Submit</button>
</form>
对于模板驱动表单来说足够直接。
对于Reactive Form,我们可以实例化该指令的实例:
var validator = new SpecificNameValidatorDirective();
并设置我们想要的名称
validator.name = "nobdy";
然后使用我们的指令实例构建我们的表单:
this.myForm = this.fb.group({
name: ['',[validator]]
});
这将自动查找validate
函数并执行它,因为各种验证器都遵循Validator interface definition。 janky部分将名称设置在一个单独的行中,而不是在构造函数中,但是我无法使用模板驱动的版本使其更好。
无论如何,有一个Plunker可供您使用。
答案 1 :(得分:1)
您可以使用与类相同的方式导出函数:
export const validateName:ValidateFn = (c: FormControl) {
return (c.value === 'rahulSingh') ? null : {
notCorrect: true
};
}
然后导入它们:
import {validateName} from '...';
this.myForm = this.fb.group({
name: ['', [validateName]]
});
答案 2 :(得分:1)
下面给出了电子邮件验证指令
import { Directive, forwardRef } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';
@Directive({
selector: '[validateEmail]',
providers: [{ provide: NG_VALIDATORS, useExisting: forwardRef(() => ValidateEmail), multi: true }]
})
export class ValidateEmail implements Validator {
constructor() { }
validate(c: AbstractControl): { [key: string]: any } {
let EMAIL_REGEXP = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i;
if (!c.value) return null;
return EMAIL_REGEXP.test(c.value) ? null : {
validEmail: true
};
}
}
下面是另一个自定义验证指令,用于将模型与另一个模型匹配。
import { Directive, ElementRef, forwardRef, Attribute } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS, FormControl } from '@angular/forms';
@Directive({
selector: '[matchControl][ngModel]',
providers: [{ provide: NG_VALIDATORS, useExisting: forwardRef(() => MatchControl), multi: true }]
})
export class MatchControl implements Validator{
constructor(@Attribute('matchControl') private matchControl: string) { }
validate(c: AbstractControl): { [key: string]: any; } {
let v = c.value;
let e = c.root.get(this.matchControl)
return (e && v !== e.value) ? {
match: true
} : null;
}
}
及其html如下
<input name="password" type="password" class="form-control" required minlength="8" maxlength="15" [(ngModel)]="user.password" #password="ngModel">
<input name="cpassword" type="password" class="form-control" required [(ngModel)]="user.cpassword" #cpassword="ngModel" matchControl="password">
希望这两个例子能帮到你