Angular2 - 模糊的FormControl验证

Ree*_*son 39 validation typescript angular-validation angular

我正在寻找添加一些基本的电子邮件验证来检查用户是否输入了正确的电子邮件地址.目前使用下面的方法,验证会在用户输入时更新,在输入一个字符后出现错误时看起来很奇怪.

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]));
Run Code Online (Sandbox Code Playgroud)

我想知道是否有可能触发对场的模糊进行验证,例如在angularJS中:

ng-model-options="{ updateOn: 'blur' }"
Run Code Online (Sandbox Code Playgroud)

我知道html中输入字段上的blur选项,但除非有办法将控件置于错误状态,否则这不会使我的控件出错.

任何人都可以帮我指出正确的方向吗?

谢谢.

编辑:我正在寻找angular2解决方案,而不是angularJS解决方案.

Ale*_*kov 51

编辑2

正如Alex官方文档所述,Angular 5.0.0版为您的ngModel提供了新选项updateOn: 'blur'

this.email = new FormControl(null, {
   validators: Validators.required,
   updateOn: 'blur'
});
Run Code Online (Sandbox Code Playgroud)

您还可以使用其他更新选项:( 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,请继续关注这个Angular 2 github线程关于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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • @DanielFranciscoSabugal 是的,这可能是个问题,但就我而言,这是一个很好的决定。用户在输入时不应该看到错误,并且在他结束后会被验证。 (2认同)

AJT*_*T82 14

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');
}
Run Code Online (Sandbox Code Playgroud)

在模板中,您需要标记验证消息不会显示,除非该字段是touched:

<div *ngIf="username.hasError('minlength') || username.hasError('required') 
              && username.touched">Required and minlength 6!
</div>
Run Code Online (Sandbox Code Playgroud)

DEMO

PS如果需要,您也可以在整个表单上标记,而不仅仅是在特定的表单控件上


小智 9

找到了一种方法,在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的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>
Run Code Online (Sandbox Code Playgroud)


小智 7

这样的事情:使用ngControl对象触及的属性.

 <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>
Run Code Online (Sandbox Code Playgroud)

  • 当元素获得焦点时,这将无助于下一次.name.focus在第一次触摸时获得其真实值,并且从第二次开始 - 在每次按键时,验证指示器将被取消. (3认同)

prz*_*cio -11

您可以

[class.has-error]="!form.controls['ctrlEmailAddress'].valid"
Run Code Online (Sandbox Code Playgroud)

一旦您更改模型,这将添加 has-error 类。所以基本上你不需要模糊来进行验证检查。

这解决了 Angular 2.0.0 beta 的问题;)