Angular2 - FormControl 验证模糊
Posted
技术标签:
【中文标题】Angular2 - FormControl 验证模糊【英文标题】:Angular2 - FormControl Validation on blur 【发布时间】:2016-02-25 07:26:50 【问题描述】:我正在考虑添加一些基本的电子邮件验证,以检查用户是否输入了正确的电子邮件地址。目前使用下面的方法,验证会随着用户键入而更新,输入一个字符后出现错误时看起来很奇怪。
validEmail(c: Control)
if(!c.value.match('[a-z0-9!#$%&\'*+/=?^_`|~-]+(?:\\.[a-z0-9!#$%&\'*+/=?^_`|~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?'))
return
validEmail: true
;
return null;
ctrlEmailAddress: Control = new Control('', Validators.compose([
Validators.required, this.validEmail]));
我想知道是否可以触发字段模糊验证,例如在 angularJS 中:
ng-model-options=" updateOn: 'blur' "
我知道 html 中输入字段上的模糊选项,但这不会使我的控件出错,除非有办法将控件置于错误状态。
谁能帮我指出正确的方向?
谢谢。
编辑:我正在寻找 angular2 解决方案,而不是 angularJS 解决方案。
【问题讨论】:
【参考方案1】:你可以
[class.has-error]="!form.controls['ctrlEmailAddress'].valid"
这将在您更改模型后立即添加 has-error 类。所以基本上你不需要模糊来进行验证检查。
这解决了 angular 2.0.0 beta 的问题;)
【讨论】:
这不能回答问题。该问题询问如何仅在模糊上进行验证。【参考方案2】:编辑 2
正如Alex 和official documentation 所说,Angular 版本 5.0.0 为您的 ngModel updateOn: 'blur'
提供了新选项
this.email = new FormControl(null,
validators: Validators.required,
updateOn: 'blur'
);
您还可以使用其他更新选项:change
(默认)、blur
、submit
。
原创
我使用指令删除焦点上的整个验证并在模糊事件后将其返回。它基于 Cristian Deschamps 的回答。
我只在模糊时更新有效性,所以如果值在焦点之前无效,它在焦点之后将无效。但如果你开始输入,有效性将被更新。
由于某些原因,清除顺序是有意义的,所以我先清除异步验证器。
任何提供的建议都会有所帮助 =)
import Directive from '@angular/core';
import NgControl from '@angular/forms';
@Directive(
selector: '[validate-onblur]',
host:
'(focus)': 'onFocus($event)',
'(blur)': 'onBlur($event)'
)
export class ValidateOnBlurDirective
private validators: any;
private asyncValidators: any;
constructor(public formControl: NgControl)
onFocus($event)
this.validators = this.formControl.control.validator;
this.asyncValidators = this.formControl.control.asyncValidator;
this.formControl.control.clearAsyncValidators();
this.formControl.control.clearValidators();
onBlur($event)
this.formControl.control.setAsyncValidators(this.asyncValidators);
this.formControl.control.setValidators(this.validators);
this.formControl.control.updateValueAndValidity();
另外,请继续关注 Angular 2 github thread 关于 onBlur 验证
编辑 1
还有另一个问题 - 如果我只是单击该字段并在单击离开后 - 将调用验证。如果您有任何关于它的通知(或服务器调用) - 它会在您每次执行时出现。所以你可以添加wasChanged
属性并像这样使用它:
@Directive(
selector: '[validate-onblur]',
host:
'(focus)': 'onFocus($event)',
'(blur)': 'onBlur($event)',
'(keyup)': 'onKeyup($event)',
'(change)': 'onChange($event)',
'(ngModelChange)': 'onNgModelChange($event)'
)
export class ValidationOnBlurDirective
private validators: any;
private asyncValidators: any;
private wasChanged: any;
constructor(public formControl: NgControl)
onFocus($event)
this.wasChanged = false;
this.validators = this.formControl.control.validator;
this.asyncValidators = this.formControl.control.asyncValidator;
this.formControl.control.clearAsyncValidators();
this.formControl.control.clearValidators();
onKeyup($event)
this.wasChanged = true; // keyboard change
onChange($event)
this.wasChanged = true; // copypaste change
onNgModelChange($event)
this.wasChanged = true; // ng-value change
onBlur($event)
this.formControl.control.setAsyncValidators(this.asyncValidators);
this.formControl.control.setValidators(this.validators);
if (this.wasChanged)
this.formControl.control.updateValueAndValidity();
【讨论】:
这种方法的问题是,如果控件在获得焦点时无效且脏,那么在第一次击键之后(我正在考虑输入文本框)它将有效验证器,并且将应用 ng-valid 类。例如,如果您将该类设置为将输入框显示为绿色,那就有问题了。我认为只要控件保持焦点,它就应该保持某种挂起状态,因此不应用 ng-valid。 @DanielFranciscoSabugal 是的,这可能是个问题,但就我而言,这是一个不错的决定。用户在输入时不应该看到错误,并且在他结束后将被验证。 @AlexShestakov 感谢这篇文章。对我来说,this.formControl.control.validator(和 asyncValidator)返回 null。我正在使用有效验证的现有反应式表单上执行此操作。有什么想法吗? 看来我在尝试 this.formControl.control.validators [复数] 而不是 this.formControl.control.validator 如果你使用FormBuilder应该怎么做?【参考方案3】:从 Angular v 5.0.0
开始,现在可以通过将 updateOn: 'blur'
标记到表单控件来实现。
这也意味着valueChanges
在模糊事件发生之前不会触发该表单控件。这是minlength
和required
的示例:
this.form = new FormGroup(
username: new FormControl('',
validators: [Validators.required, Validators.minLength(6)], updateOn: 'blur' )
)
get username()
return this.form.get('username');
您希望在模板中标记验证消息不会显示,除非该字段为touched
:
<div *ngIf="username.hasError('minlength') || username.hasError('required')
&& username.touched">Required and minlength 6!
</div>
DEMO
P.S 如果需要,您还可以在整个表单上标记它,而不仅仅是在特定的表单控件上
【讨论】:
使用此语法时,FormControl 构造函数中的第二个参数为 AbstractControlOptions 类型,异步验证器设置如下: this.form = new FormGroup( username: new FormControl('', 验证器:[Validators.required, Validators.minLength(6)], asyncValidators: yourAsyncFunction, updateOn: 'blur' ) ) 如果你使用FormBuilder应该怎么做? 任何希望它与 Validator.compose() 一起工作的人都可以参考这个***.com/questions/50103342/…【参考方案4】:我已经改进了一点 Alex Shestakov 解决方案,顺便说一下,它已经起作用了,以避免在保持焦点的同时将控制状态设置为有效。
@Directive(
selector: '[validate-onblur]',
host:
'(focus)': 'onFocus($event)',
'(blur)' : 'onBlur($event)'
)
export class ValidateOnBlurDirective
private validators: any;
private asyncValidators: any;
private hasFocus = false;
constructor(public formControl: NgControl)
onFocus($event)
this.hasFocus = true;
this.validators = this.formControl.control.validator;
this.asyncValidators = this.formControl.control.asyncValidator;
this.formControl.control.clearAsyncValidators();
this.formControl.control.clearValidators();
this.formControl.control.valueChanges
.filter(() => this.hasFocus)
.subscribe(() => this.formControl.control.markAsPending());
onBlur($event)
this.hasFocus = false;
this.formControl.control.setAsyncValidators(this.asyncValidators);
this.formControl.control.setValidators(this.validators);
this.formControl.control.updateValueAndValidity();
这样,只要保持焦点,控件就会一直处于挂起状态。这将有助于避免控件在获得焦点之前无效,然后一旦用户开始在其上输入,它就被标记为有效,在模糊事件发生之前,再次设置验证器并且真正的有效性应该确定控制。
【讨论】:
【参考方案5】:在 rc6 中找到了一种方法。
1- 创建指令:validate-onblur.directive.ts
@Directive(
selector: '[validate-onblur]',
host:
'(focus)': 'onFocus($event)',
'(blur)': 'onBlur($event)'
)
export class ValidateOnBlurDirective
constructor(public formControl: NgControl)
onFocus($event)
this.formControl.control.markAsUntouched(false);
onBlur($event)
this.formControl.control.markAsTouched(true);
然后在您的 html 模板中将指令添加到您的表单中,我的示例使用 ReactiveFormsModule 模型。
然后将此添加到您的错误消息中:
<input type="text" formControlName="full_name" validate-onblur />
<span *ngIf="formAccountDetails.controls.full_name.touched && !formAccountDetails.controls.full_name.valid && !formAccountDetails.controls.full_name.pristine" class="errors">
...
</span>
【讨论】:
【参考方案6】:类似这样的: 使用 ngControl 对象的属性 touched。
<div class="form-group" [class.has-error]="!name.valid && name.touched">
<label for="name">Name</label>
<input #name="ngForm" ngControl="name" name="name" type="text" class="form-control" required>
</div>
【讨论】:
这在下次元素获得焦点时无济于事。 name.focus 在第一次触摸时获得其真实值,从第二次开始 - 验证指示器将在每次按键时显示。以上是关于Angular2 - FormControl 验证模糊的主要内容,如果未能解决你的问题,请参考以下文章
在新的 Angular 2 表单中将 NgModel 绑定到 FormControl
无法绑定到“formControl”,因为它不是“输入”的已知属性 - Angular2 Material Autocomplete 问题