Forms 角度2-警告/提示的表单验证
我正在尝试添加不会使表单无效的表单验证。验证应仅显示为警告 例如,年龄验证。年龄大于90表示警告,年龄大于120表示错误 我在表单上尝试了两个FormGroup,在输入字段上尝试了两个[formControl]。仅使用第一个[formControl]Forms 角度2-警告/提示的表单验证,forms,validation,angular,Forms,Validation,Angular,我正在尝试添加不会使表单无效的表单验证。验证应仅显示为警告 例如,年龄验证。年龄大于90表示警告,年龄大于120表示错误 我在表单上尝试了两个FormGroup,在输入字段上尝试了两个[formControl]。仅使用第一个[formControl] 这种验证是否可以使用Angulars表单验证?哪种方法是正确的选择?我可能会这样做 <form #form="ngForm" (ngSubmit)="save()"> <input formControlName="cont
这种验证是否可以使用Angulars表单验证?哪种方法是正确的选择?我可能会这样做
<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>
警告:年龄限制很高。。
错误:超出了年龄限制。。
正常
通过angular.io可以很容易地进行表单验证,提示您可以在其上阅读文档
但我的脑海中可能有类似的方法可以更好地帮助你
首先,我们创建一个名为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(); //
}
}
<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>
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;
}
}
}
首先,我们应该为反应式表单注入FormBuilder(不要忘记在主模块中导入反应式FormModule),然后在[buildForm()]方法中,我们在表单属性上构建一组表单,该属性是从抽象类表单继承的
然后在下一步中,我们创建一个订阅表单值更改,并在值更改时调用[onValueChanged()]方法
在[onValueChanged()]方法中,我们检查表单的字段是否有效,如果无效,则从受保护的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>
希望我能帮上忙。我通过创建自定义验证器实现了这一点,它总是返回
null
。此外,此验证器还会创建其他属性警告
。然后从您的视图中简单地检查这个属性
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");
}
}
导出接口AbstractControlWarn扩展AbstractControl{warnings:any;}
导出函数tooBigAgeWarning(c:AbstractControlWarn){
如果(!c.value){返回null;}
设val=+c.value;
c、 warnings=val>90&&val 120?{impossibleAge:{val}}}:null;
}
@组成部分({
选择器:“我的应用程序”,
模板:`
年龄:
错误!年龄是必需的
错误!年龄大于120
警告!年龄大于90岁
发送
`,
})
导出类应用程序{
年龄:对照组;
构造函数(私有_fb:FormBuilder){}
恩戈尼尼特(){
this.form=this.\u fb.group({
年龄:[''[
需要验证器,
tooBigAgeWarning,
不可能验证程序]]
})
this.age=this.form.get(“age”);
}
}
示例:接受的答案在开发模式下工作得非常完美,但如果您尝试在--prod模式下构建,则会出现此错误
... Property 'warnings' does not exist on type 'FormControl'.
为了修复这个错误,我对原始代码(App类)进行了调整,基本上是为了修复松散类型的变量。这是新版本:
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])
});
}
}
导出类FormControlWarn扩展FormControl{warnings:any;}
导出函数tooBigAgeWarning(c:FormControlWarn){
如果(!c.value){返回null;}
设val=+c.value;
c、 warnings=val>90&&val 120?{impossibleAge:{val}}}:null;
}
@组成部分({
选择器:“我的应用程序”,
模板:`
年龄:
错误!年龄是必需的
错误!年龄大于120
警告!年龄大于90岁
发送
`,
})
导出类应用程序{
获取年龄():FormControlWarn{
返回此.form.get(“年龄”);
}
构造函数(私有_fb:FormBuilder){}
恩戈尼尼特(){
this.form=this.\u fb.group({
年龄:新FormControlWarn(“”[
需要验证器,
tooBigAgeWarning,
不可能验证程序])
});
}
}
感谢您的回复!这是一个很好的解决方案,但我使用的是一个更通用的解决方案,其中表单字段和验证是动态生成的,因此我无法硬编码验证。感谢您花时间阅读详细文章,但我没有看到在一个字段上有两个不同的验证,其中第一个会产生错误并使验证无效窗体,另一个仅显示警告。请参见“年龄”字段中的“我的描述”。我想在一个字段上添加两个Validator.minLength。明白了,您的问题可以通过自定义验证来解决;我将更新答案。我已将以下输出添加到您的form.component.html{{{form.controls.age.valid}{{form.valid}}。表单和字段也在91上。其思想是告诉自定义验证不应使表单无效,但仍应添加消息?在该策略中,基于验证错误添加消息还包括hasError()方法给出的表单和字段有效属性,这意味着如果存在错误,则字段和表单无效。因此,您的问题无法通过此策略解决。(我认为您的问题需要在angular2 AbstractControl中进行一些编辑。)好的简单解决方案!非常感谢。嘿快速提问如果我们已经使用了ngIf,为什么需要[hidden]=“age.pristine”
?那太棒了!!很高兴我找到了这个答案,谢谢!
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])
});
}
}