我正在尝试添加不会使表单无效的表单验证 . 验证应仅显示为警告 .
例如 . 年龄验证 . 年龄大于90表示警告,年龄大于120表示错误 .
我已尝试在表单上使用两个FormGroup,在输入字段上使用两个[formControl] . 仅使用第一个[formControl] .
是否可以使用Angulars表单验证进行此类验证?要走哪条路?
我通过创建自定义验证器来完成它,它始终返回 null . 此验证器还会创建其他属性 warnings . 然后从您的视图中简单地检查此属性 .
null
warnings
export interface AbstractControlWarn extends AbstractControl { warnings: any; } export function tooBigAgeWarning(c: AbstractControlWarn) { if (!c.value) { return null; } let val = +c.value; c.warnings = val > 90 && val <= 120 ? { tooBigAge: {val} } : null; return null; } export function impossibleAgeValidator(c: AbstractControl) { if (tooBigAgeWarning(c) !== null) { return null; } let val = +c.value; return val > 120 ? { impossibleAge: {val} } : null; } @Component({ selector: 'my-app', template: ` <div [formGroup]="form"> Age: <input formControlName="age"/> <div *ngIf="age.errors?.required" [hidden]="age.pristine"> Error! Age is required </div> <div *ngIf="age.errors?.impossibleAge" [hidden]="age.pristine"> Error! Age is greater then 120 </div> <div *ngIf="age.warnings?.tooBigAge" [hidden]="age.pristine"> Warning! Age is greater then 90 </div> <p><button type=button [disabled]="!form.valid">Send</button> </div> `, }) export class App { age: FormControl; constructor(private _fb: FormBuilder) { } ngOnInit() { this.form = this._fb.group({ age: ['', [ Validators.required, tooBigAgeWarning, impossibleAgeValidator]] }) this.age = this.form.get("age"); } }
示例:https://plnkr.co/edit/me0pHePkcM5xPQ7nzJwZ?p=preview
好
通过angular.io可以很容易地进行表单验证,暗示你可以在https://angular.io/docs/ts/latest/cookbook/form-validation.html上阅读文档
但是可以在我脑海里想出类似的方式来帮助你 .
首先我们创建一个名为Form的抽象类,它包含一些常用的函数和属性 .
import {FormGroup} from "@angular/forms"; export abstract class Form { form: FormGroup; protected abstract formErrors: Object; protected abstract validationMessages: Object; onValueChanged(data?: any) { if (!this.form) { return; } const form = this.form; for (const field in this.formErrors) { this.formErrors[field] = ''; const control = form.get(field); if (control && control.dirty && !control.valid) { const messages = this.validationMessages[field]; for (const key in control.errors) { this.formErrors[field] = messages[key]; break; } } } } }
那么你应该创建一个表单组件,例如名为LoginComponent,如下所示
import {Component, OnInit} from "@angular/core"; import {Form} from "./form"; import {Validators, FormBuilder} from "@angular/forms"; @Component({ templateUrl: '...' }) export class LoginComponent extends Form implements OnInit { protected formErrors = { 'email': '', 'password': '' } protected validationMessages = { 'email': { 'required': 'email required message', 'email': 'email validation message' }, 'password': { 'required': 'password required message', 'minlength': 'password min length message', 'maxlength': 'password max length message', } } constructor(private _fb: FormBuilder) { } ngOnInit() { this.buildForm(); } buildForm() { this.form = this._fb.group({ 'email': ['', [ Validators.required, // emailValidator ]], 'password': ['', [ Validators.required, Validators.minLength(8), Validators.maxLength(30) ]] }); this.form.valueChanges .subscribe(data => this.onValueChanged(data)); this.onValueChanged(); // } }
首先我们应该为反应形式注入FormBuilder(不要忘记在主模块中导入ReactiveFormModule)然后在[buildForm()]方法中我们在表单属性上构建一组表单,该表单继承自抽象类Form .
接下来我们创建一个表单值更改的订阅,并在值更改时调用[onValueChanged()]方法 .
在[onValueChanged()]方法中,我们检查表单的字段是否有效,如果不是,我们从protected validationMessages属性中获取消息并在formErrors属性中显示它 .
那么你的模板应该类似于此
<div class="col-md-4 col-md-offset-4"> <form [formGroup]="form" novalidate> <div class="form-group"> <label class="control-label" for="email">email</label> <input type="email" formControlName="email" id="email" class="form-control" required> <div class="help help-block" *ngIf="formErrors.email"> <p>{{ formErrors.email }}</p> </div> </div> <div class="form-group"> <label class="control-label" for="password">password</label> <input type="password" formControlName="password" id="password" class="form-control" required> <div class="help help-block" *ngIf="formErrors.password"> <p>{{ formErrors.password }}</p> </div> </div> <div class="form-group"> <button type="submit" class="btn btn-block btn-primary" [disabled]="!form.valid">login</button> </div> </form> </div>
模板是如此简单,内部您检查字段是否有错误,如果有错误绑定 .
对于bootstrap,你可以做下面的其他事情
<div class="form-group" [ngClass]="{'has-error': form.controls['email'].dirty && !form.controls['email'].valid, 'has-success': form.controls['email'].valid}"> <label class="control-label" for="email">email</label> <input type="email" formControlName="email" id="email" class="form-control" required> <div class="help help-block" *ngIf="formErrors.email"> <p>{{ formErrors.email }}</p> </div> </div>
UPDATE: 我试图为你创建一个非常简单但几乎完整的样本,你当然可以开发更狂野的规模:https://embed.plnkr.co/ExRUOtSrJV9VQfsRfkkJ/
但有一点描述,你可以创建如下的自定义验证
import {ValidatorFn, AbstractControl} from '@angular/forms'; function isEmptyInputValue(value: any) { return value == null || typeof value === 'string' && value.length === 0; } export class MQValidators { static age(max: number, validatorName: string = 'age'): ValidatorFn { return (control: AbstractControl): {[key: string]: any} => { if (isEmptyInputValue(control.value)) return null; const value = typeof control.value == 'number' ? control.value : parseInt(control.value); if (isNaN(value)) return null; if (value <= max) return null; let result = {}; result[validatorName] = {valid: false}; return result; } } }
这个自定义验证器得到一个名为validatorName的可选参数,这个参数会导致您指定多个类似的验证,如示例中的formComponent应如下所示:
buildForm () { this.form = this._fb.group({ 'age': ['', [ Validators.required, Validators.pattern('[0-9]*'), MQValidators.age(90, 'abnormalAge'), MQValidators.age(120, 'incredibleAge') ]] }); this.form.valueChanges .subscribe(data => this.onValueChanged(data)); this.onValueChanged(); } onValueChanged(data?: any): void { if (!this.form) { return; } const form = this.form; for (const field in this.formErrors) { this.formErrors[field] = ''; const control = form.get(field); if (control && control.dirty && !control.valid) { const messages = this.validationMessages[field]; for (const key in control.errors) { this.formErrors[field] = messages[key]; } } } } formErrors = { age: '' } validationMessages = { 'age': { 'required': 'age is required.', 'pattern': 'age should be integer.', 'abnormalAge': 'age higher than 90 is abnormal !!!', 'incredibleAge': 'age higher than 120 is incredible !!!' } }
希望我帮忙 .
Sergey Voronezhskiy中接受的答案在开发模式下完美无缺,但如果您尝试构建--prod模式,则会出现此错误 .
... Property 'warnings' does not exist on type 'FormControl'.
为了修复这个错误,我对原始代码进行了调整,基本上修复了松散类型的变量,这是新版本:
export class FormControlWarn extends FormControl { warnings: any; } export function tooBigAgeWarning(c: FormControlWarn ) { if (!c.value) { return null; } let val = +c.value; c.warnings = val > 90 && val <= 120 ? { tooBigAge: {val} } : null; return null; } export function impossibleAgeValidator(c: AbstractControl) { if (tooBigAgeWarning(c) !== null) { return null; } let val = +c.value; return val > 120 ? { impossibleAge: {val} } : null; } @Component({ selector: 'my-app', template: ` <div [formGroup]="form"> Age: <input formControlName="age"/> <div *ngIf="age.errors?.required" [hidden]="age.pristine"> Error! Age is required </div> <div *ngIf="age.errors?.impossibleAge" [hidden]="age.pristine"> Error! Age is greater then 120 </div> <div *ngIf="age.warnings?.tooBigAge" [hidden]="age.pristine"> Warning! Age is greater then 90 </div> <p><button type=button [disabled]="!form.valid">Send</button> </div> `, }) export class App { get age(): FormControlWarn{ return <FormControlWarn>this.form.get("age"); } constructor(private _fb: FormBuilder) { } ngOnInit() { this.form = this._fb.group({ age: new FormControlWarn('', [ Validators.required, tooBigAgeWarning, impossibleAgeValidator]) }); } }
这可能就是我如何做到的 .
<form #form="ngForm" (ngSubmit)="save()"> <input formControlName="controlName"> <span *ngIf="form.pristine && form.controls.controlName.value > 90 && form.controls.controlName.value < 120"> Warning: Age limit is high.. </span> <span *ngIf="form.pristine && form.controls.controlName.value > 120"> Error: Age limit exceeded.. </span> <form>
4 回答
我通过创建自定义验证器来完成它,它始终返回
null
. 此验证器还会创建其他属性warnings
. 然后从您的视图中简单地检查此属性 .示例:https://plnkr.co/edit/me0pHePkcM5xPQ7nzJwZ?p=preview
好
通过angular.io可以很容易地进行表单验证,暗示你可以在https://angular.io/docs/ts/latest/cookbook/form-validation.html上阅读文档
但是可以在我脑海里想出类似的方式来帮助你 .
首先我们创建一个名为Form的抽象类,它包含一些常用的函数和属性 .
那么你应该创建一个表单组件,例如名为LoginComponent,如下所示
首先我们应该为反应形式注入FormBuilder(不要忘记在主模块中导入ReactiveFormModule)然后在[buildForm()]方法中我们在表单属性上构建一组表单,该表单继承自抽象类Form .
接下来我们创建一个表单值更改的订阅,并在值更改时调用[onValueChanged()]方法 .
在[onValueChanged()]方法中,我们检查表单的字段是否有效,如果不是,我们从protected validationMessages属性中获取消息并在formErrors属性中显示它 .
那么你的模板应该类似于此
模板是如此简单,内部您检查字段是否有错误,如果有错误绑定 .
对于bootstrap,你可以做下面的其他事情
UPDATE: 我试图为你创建一个非常简单但几乎完整的样本,你当然可以开发更狂野的规模:https://embed.plnkr.co/ExRUOtSrJV9VQfsRfkkJ/
但有一点描述,你可以创建如下的自定义验证
这个自定义验证器得到一个名为validatorName的可选参数,这个参数会导致您指定多个类似的验证,如示例中的formComponent应如下所示:
希望我帮忙 .
Sergey Voronezhskiy中接受的答案在开发模式下完美无缺,但如果您尝试构建--prod模式,则会出现此错误 .
为了修复这个错误,我对原始代码进行了调整,基本上修复了松散类型的变量,这是新版本:
这可能就是我如何做到的 .