ユーザーが正しい電子メールアドレスを入力したことを確認するために、基本的な電子メール検証を追加することを検討しています。現在、以下の方法を使用して、ユーザーが入力すると検証が更新され、1文字を入力した後にエラーが発生すると奇妙に見えます。
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内の入力フィールドのぼかしオプションを知っていますが、これはコントロールをエラー状態にする方法がない限り、コントロールをエラーにしません。
誰かが正しい方向に私を向けるのを手伝ってもらえますか?
ありがとう。
編集:私はangularJSソリューションではなく、angular2ソリューションを探しています。
EDIT 2
Alex および 公式ドキュメント のように、Angularバージョン5.0.0には新しいオプションがありますngModel updateOn: 'blur'
this.email = new FormControl(null, {
validators: Validators.required,
updateOn: 'blur'
});
また、change
(デフォルト)、blur
、submit
などの他の更新オプションを使用できます。
オリジナル
フォーカスの検証全体を削除し、ぼかしイベントの後にそれを返すディレクティブを使用します。クリスティアン・デシャンの答えに基づいています。
私はぼかしでのみ有効性を更新するので、フォーカス前に値が無効だった場合、その後は無効になります。ただし、入力を開始すると、有効性が更新されます。
何らかの理由で順序のクリアが理にかなっているので、最初に非同期検証をクリアします。
提供された提案は役に立ちます=)
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検証について
EDIT 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();
}
}
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>
P.S必要に応じて、特定のフォームコントロールだけでなく、フォーム全体にもマークを付けることができます
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>
次のようなものを使用します:touchedのプロパティを使用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>
アレックスシェスタコフのソリューションを少し改善しました。これは、フォーカスを維持しながら値が変化したときにコントロール状態を有効に設定することを避けるために、既に機能しています。
@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();
}
}
このようにして、コントロールはフォーカスを保持している限り、保留状態のままになります。これにより、コントロールがフォーカスを取得する前に無効になり、ユーザーが入力を開始するとすぐに、ぼかしイベントが発生する前に、バリデーターが再設定され、コントロールを決定する必要があります。