2017-11-05 4 views
1

Ich brauchte eine Validierung, die prüft, ob email gleich Email Confirm ist. Dazu habe ich eine benutzerdefinierte Validierung, die angular4: benutzerdefinierte 'gleich' Validierung mit valueChanges beobachtbar

import { AbstractControl, ValidationErrors, FormGroup } from '@angular/forms'; 

export function ValidateEqual(equals: string) { 
    return (control: AbstractControl): ValidationErrors | null => { 

    const equalsField = control.root.get(equals) 
    if (equalsField) { 

     equalsField.valueChanges.subscribe(value => { 
     console.log('observable fired', value); 
     // control.updateValueAndValidity({ onlySelf: true , emitEvent: false }); 
     }); 
     if (control.value !== equalsField.value) { 
     return { equals: true }; 
     } 
    } 
    return null; 
    } 
} 

und meine Form sieht aus wie

das Feld am Übergang mit I
this.loginForm = this.fb.group({ 
    password: [ '', [ 
    Validators.required, 
    ] ], 
    email: [ '', [ 
    Validators.required, 
    Validators.email, 
    ] ], 
    emailConfirm: [ '', [ 
    Validators.required, 
    Validators.email, 
    ValidateEqual('email'), 
    ] ] 
}); 

So in ValidateEqual() als Argument Gleichheit zu prüfen, wie

aussieht. Das funktioniert gut.

Das folgende Szenario schlägt fehl:

1)

E-Mail: [email protected]

bestätigen E-Mail: [email protected]

* jetzt E-Mail bestätigen zeigt einen Fehler, Es ist nicht gleich "E-Mail". Richtig.

2)

* jetzt ändere ich das email Feld confirm email Feld übereinstimmen.

E-Mail: [email protected]

bestätigen E-Mail: [email protected]

* Der Fehler auf dem confirm email Feld verschwindet nicht, weil es nicht bekannt, dass Veränderung.

Das Problem, das ich habe, ist, dass ich die valueChanges beobachtbaren auf dem Gleichheits Feld zu verwenden versuchen das control Feld zu haben, um wieder Validate, aber wenn ich control.updateValueAndValidity() ermögliche es exponentiell auf jedem Tastendruck wird die Anmeldung und der Browser stürzt ab . Die IT benachrichtigt das Feld email confirm erneut, damit es fast funktioniert ... fast.

Hat jemand eine Idee, wie man es nur einmal abonnieren und es die control Feld erneut validieren lassen, ohne erneut zu abonnieren (und wieder ...)?

+0

Karo dieses heraus: https://stackoverflow.com/questions/43487413/password- und-bestätigen-Passwort-Feld-Validierung-angular2-reaktive-Formen – Alex

Antwort

1

Das Problem mit diesem Code hinzufügen, ist, dass ValidatorFn platziert auf einem FormControl wird natürlich nur überprüft, wenn der Wert dieses FormControl ändert. Was wir wollen, ist zu überprüfen, wenn entweder email oder emailConfirm ändert. Um dies zu erreichen, müssen wir die FormGroup und nicht nur ein FormControl validieren. Weil eine ValidatorFn eine AbstractControl empfängt, bedeutet dies, dass unsere Funktion eine FormGroup, FormControl oder FormArray erhalten kann.

static matches(form: AbstractControl){ 
    return form.get('email').value == form.get('emailConfirm').value ? null : {equals: true}; 
} 

nun in Ihrer Komponente, müssen Sie noch diese Prüfung hinzuzufügen und es ist ein bisschen anders:

this.form = this.fb.group({...}, {validator: CustomValidator.matches}); 

Wie Sie sehen können wir es ein zweites Objekt als Argument übergeben, die Validatoren nimmt für die gesamte FormGroup

in Ihrer Vorlage möchten Sie überprüfen, ob die gesamte Form des Gleichen Fehler anstelle eines einzelnen Formcontrol hat:

<div *ngIf="form.hasError('equals')">The emails don't match</div> 
3

Dies ist eine Möglichkeit, zwei E-Mail zu überprüfen, sind die gleichen oder nicht in Ihrer validate gleichen Klasse schreibt diesen Code

export class emailValidation { 
    static matchEmail(AC: AbstractControl){ 
     let email=AC.get('email').value; 
     let emailConfirm=AC.get('emailConfirm').value; 
     if(email!=emailConfirm){ 
      console.log(false); 
     } 
    } 
} 

und in Ihrer Komponente

this.loginForm = this.fb.group({ 
    password: [ '', [ 
    Validators.required, 
    ] ], 
    email: [ '', [ 
    Validators.required, 
    Validators.email, 
    ] ], 
    emailConfirm: [ '', [ 
    Validators.required, 
    Validators.email, 
    ] ] 
}, 
{ 
    validator:passwordValidation.matchPassword 
    }); 
0

Danke Jungs für die guten Beispiele. Ich mache dies sinnvollerweise auf dem Formular und nicht auf einem Formularsteuerelement, da es nicht weiß, wie auf andere Steuerelemente reagiert werden soll.

Ich habe eine kleine Optimierung vorgenommen, damit ich die Felder, die im Equal Validator verglichen werden, kontrollieren kann. Ich habe auch den Fehler auf der field2 Steuerung, so dass ich eine separate Fehlermeldung nicht irgendwo unter meinen Feldern hinzufügen muß (I Material Design mat-Form-Felder verwenden):

interface IEmailMatchFields { 
    field1: string; 
    field2: string; 
} 
export class EmailMatch { 

    fields: IEmailMatchFields; 
    constructor(fields: IEmailMatchFields) { 
    this.fields = fields; 
    } 
    emailMatches(form: AbstractControl) { 

    if (this.fields) { 
     if (form.get(this.fields.field1).value == form.get(this.fields.field2).value) { 
     form.get(this.fields.field2).setErrors({ 'emailNotEq': false }); 
     form.get(this.fields.field2).updateValueAndValidity({ onlySelf: true }); 
     return null; 
     } else { 
     form.get(this.fields.field2).setErrors({ 'emailNotEq': true }); 
     return { emailNotEq: true }; 
     } 
    } 
    } 
} 

export class MyComponent implements OnInit { 
    emailMatch: EmailMatch; 
    registerForm: FormGroup; 

    constructor(
    private fb: FormBuilder 
) { 
    this.emailMatch = new EmailMatch({ field1: 'email', field2: 'emailConfirm' }); 
    } 

    ngOnInit(): void { 
    this.registerForm = this.fb.group({ 
     password: [ '', [ 
     Validators.required, 
     ] ], 
     email: [ '', [ 
     Validators.required, 
     Validators.email, 
     ] ], 
     emailConfirm: [ '', [ 
     Validators.required, 
     Validators.email, 
     ] ] 
    }, { 
     validator: this.emailMatch.emailMatches.bind(this.emailMatch) 
    }); 
    } 
} 

Ich denke, statt field1 und field2 können Sie auch Referenzen der 2 Formcontrols übergeben, aber dann müssen Sie die Formcontrols zu Ihrer Formulargruppe usw. hinzufügen. Ich denke, das Senden der Schlüssel funktioniert gut.

2

Ich würde empfehlen, dass Sie ngx-validation auf github betrachten. Es ist eine kleine Open-Source-lib, können Sie entweder direkt verwenden oder Gabel oder einfach sehen, wie sie es dort taten:

Verwandte Themen