2015-11-23 4 views
20

Ich bin dabei, einige grundlegende E-Mail-Validierung hinzufügen, um zu überprüfen, dass der Benutzer eine korrekte E-Mail-Adresse eingegeben hat. Wenn Sie die unten beschriebene Methode verwenden, wird die Validierung aktualisiert, wenn der Benutzer eingibt, was merkwürdig aussieht, wenn nach der Eingabe eines Zeichens ein Fehler auftritt.Angular2 - FormControl Validierung auf Unschärfe

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])); 

ich mich gefragt, ob es möglich ist, die Validierung auf Unschärfe des Feldes auslösen, wie in AngularJS mit:

ng-model-options="{ updateOn: 'blur' }" 

Ich bin mir bewusst, die Unschärfe Option auf dem Eingabefeld innerhalb der html, aber das bringt mein Steuerelement nicht in Fehler, außer es gibt eine Möglichkeit, das Steuerelement in einen Fehlerzustand zu versetzen.

Könnte mir jemand helfen, mich in die richtige Richtung zu weisen?

Danke.

Edit: Ich bin auf der Suche nach einer angular2 Lösung, keine angularJS Lösung.

Antwort

-2

Sie können

[class.has-error]="!form.controls['ctrlEmailAddress'].valid" 

Dies fügt hat-Fehlerklasse, sobald Sie Modell ändern wird. Sie müssen also im Grunde nicht verwischen, um eine Validierungsprüfung durchzuführen.

6

Etwas wie folgt aus: Verwenden Eigenschaft berührt der ngControl Objekt.

<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> 
+3

Dies wird nicht beim nächsten Mal helfen, wenn Element den Fokus erhalten. name.focus erhält seinen wahren Wert bei der ersten Berührung und beim zweiten Mal - der Validierungsindikator wird bei jedem Tastendruck nicht mehr angezeigt. – user2783091

6

Gefunden einen Weg, in RC6.

1- Erstellen Sie eine Richtlinie: Validierung-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); 
    } 
} 

Dann in Ihrem HTML-Vorlage fügen Sie einfach die Richtlinie zum Formular, mein Beispiel das ReactiveFormsModule Modell verwenden.

Dann fügen Sie diese an Ihre Fehlermeldung:

<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> 
24

EDIT 2

Wie Alex und die official documentation sagt, Angular Version 5.0.0 hat neue Option für Ihre ngModel updateOn: 'blur'

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

Auch Sie kann andere Update-Optionen verwenden: change (Standard), blur, submit.


Original-

I-Direktive verwenden, wo ganze Validierung Fokus entfernen und sendet es zurück nach Unschärfe Ereignisse. Es basiert auf Cristian Deschamps Antwort.

I aktualisieren Gültigkeit nur auf verwischen, so dass, wenn Wert vor Fokus ungültig war, wird es nach ungültig. Wenn Sie jedoch die Eingabe starten, wird die Gültigkeit aktualisiert.

Aus irgendwelchen Gründen Clearing um Sinn machen, so dass ich klar Asynchron-Validierer zuerst.

Jede bereitgestellt Vorschlag wird hilfreich sein =)

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(); 
    } 
} 

Sie bitte auch auf dieser Angular 2 github thread über onBlur Validierung


EDIT 1

Es gibt ein weiteres Problem bleibt dran - wenn ich nur auf das Feld klicke und nach Klick weg - Validierung wird aufgerufen. Wenn Sie eine Benachrichtigung darüber (oder Serveraufrufe) haben, wird es jedes Mal angezeigt, wenn Sie es tun. So können Sie wasChanged Eigenschaft hinzufügen und es wie folgt verwendet werden:

@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(); 
     } 
    } 
+1

Das Problem bei diesem Ansatz ist, dass, wenn die Steuerung ungültig und schmutzig ist, wenn es den Fokus erhält, dann nach dem ersten Tastendruck (I eines Eingabetextfeld denke) es ohne Validatoren gültig sein wird, und die ng-valid Klasse wird angewendet. Wenn Sie diese Klasse so formatieren, dass das Eingabefeld beispielsweise grün angezeigt wird, ist das ein Problem. Ich denke, es sollte irgendwie ausstehenden Zustand beibehalten, solange das Steuerelement den Fokus behält, so dass ng-valid nicht angewendet wird. –

+1

@DanielFranciscoSabugal Ja, es kann ein Problem sein, aber in meinem Fall war es eine gute Entscheidung. Der Benutzer sollte keine Fehler sehen, während er Eingaben macht, und es wird validiert, wenn er beendet ist. –

+0

@AlexShestakov Danke für diesen Beitrag. Für mich kommt der this.formControl.control.validator (und asyncValidator) null zurück. Ich mache dies auf einer bestehenden reaktiven Form mit funktionierender Validierung. Irgendwelche Ideen? – snowBlind

2

ich ein wenig Alex Shestakov Lösung verbessert haben, die bereits durch die Art und Weise gearbeitet, um den Steuerzustand gültig zu vermeiden eingestellt wird, wenn sich sein Wert ändert während es den Fokus behält.

@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(); 
    } 
} 

Auf diese Weise bleibt die Steuerung im Status "Ausstehend", solange der Fokus beibehalten wird. Dies wird helfen, den Fall zu vermeiden, wenn ein Steuerelement ungültig ist, bevor es den Fokus erhält, und dann, sobald der Benutzer darauf tippt, wird es als gültig markiert, bevor das Unschärfeereignis eintritt, wenn die Validatoren erneut gesetzt werden und die tatsächliche Gültigkeit von Die Kontrolle sollte bestimmt werden.

5

Ab Winkel v 5.0.0 Dies ist jetzt möglich, indem Sie an die Formularsteuerung markieren.

Dies bedeutet auch, dass valueChanges nicht für diese Form Kontrolle abfeuert, bis die Unschärfe Ereignis eintritt. Hier ist ein Beispiel wiht minlength zusammen mit required:

this.form = new FormGroup({ 
    username: new FormControl('', { 
    validators: [Validators.required, Validators.minLength(6)], updateOn: 'blur'}) 
}) 

get username() { 
    return this.form.get('username'); 
} 

In der Vorlage möchten Sie würden markieren, dass die Überprüfungsmeldung wird nicht angezeigt, es sei denn das Feld ist touched:

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

DEMO

PS Wenn Sie auch benötigt wird, kann diese Markierung auf der w Loch Form, nicht nur auf einer bestimmten Form Kontrolle