Angular2-Validator, der auf mehreren Formularfeldern basiert

117

Ist es möglich, einen Validator zu erstellen, der anhand mehrerer Werte entscheiden kann, ob mein Feld gültig ist?

Wenn die bevorzugte Kontaktmethode des Kunden beispielsweise per E-Mail ist, sollte das E-Mail-Feld erforderlich sein.

Vielen Dank.


Aktualisiert mit Beispielcode ...


    import {Component, View} from 'angular2/angular2';
    import {FormBuilder, Validators, formDirectives, ControlGroup} from 'angular2/forms';

    @Component({
        selector: 'customer-basic',
        viewInjector: [FormBuilder]
    })
    @View({
        templateUrl: 'app/components/customerBasic/customerBasic.html',
        directives: [formDirectives]
    })
    export class CustomerBasic {
        customerForm: ControlGroup;

        constructor(builder: FormBuilder) {
            this.customerForm = builder.group({
                firstname: [''],
                lastname: [''],
                validateZip: ['yes'],
                zipcode: ['', this.zipCodeValidator] 
                // I only want to validate using the function below if the validateZip control is set to 'yes'
            });
        }

        zipCodeValidator(control) {
            if (!control.value.match(/\d\d\d\d\d(-\d\d\d\d)?/)) {
                return { invalidZipCode: true };
            }
        }

    }
Simon
quelle
Ja. Und wenn Sie uns Ihren Code zeigen, können wir eine bestimmte Antwort hinzufügen.
Michelem
Ich habe ein einfaches Beispiel hinzugefügt. Wie kann ich im Beispielcode die Postleitzahl nur validieren, wenn das vorherige validateZip-Steuerelement 'yes' enthält?
Simon
Simon, warum nicht die Antwort auf deine Frage bewerben?
Superjos
6
Ok, um zukünftigen Besuchern dieser Frage viel Frust zu ersparen, empfehle ich dringend, dieses NPM-Paket zu verwenden: npmjs.com/package/ng2-validation . Es hat bauen in equalund equalToMethoden und gute Dokumentation!
Michelangelo
2
Winkeldokumentation
ElliotSchmelliot

Antworten:

146

Um die Methoden, die andere veröffentlicht haben, noch einmal zu wiederholen, habe ich auf diese Weise FormGroupValidatoren erstellt, an denen nicht mehrere Gruppen beteiligt sind.

Geben Sie in diesem Beispiel einfach die Schlüsselnamen der Felder passwordund an confirmPassword.

// Example use of FormBuilder, FormGroups, and FormControls
this.registrationForm = fb.group({
  dob: ['', Validators.required],
  email: ['', Validators.compose([Validators.required,  emailValidator])],
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
  firstName: ['', Validators.required],
  lastName: ['', Validators.required]
}, {validator: matchingPasswords('password', 'confirmPassword')})

Um ValidatorsParameter zu übernehmen, müssen sie a functionentweder mit a FormGroupoder FormControlals Parameter zurückgeben. In diesem Fall validiere ich a FormGroup.

function matchingPasswords(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): {[key: string]: any} => {
    let password = group.controls[passwordKey];
    let confirmPassword = group.controls[confirmPasswordKey];

    if (password.value !== confirmPassword.value) {
      return {
        mismatchedPasswords: true
      };
    }
  }
}

Technisch hätte ich zwei beliebige Werte validieren können, wenn ich ihre Schlüssel gekannt hätte, aber ich bevorzuge es, meinen Namen Validatorsgenauso zu benennen wie den Fehler, den sie zurückgeben werden. Die Funktion könnte geändert werden, um einen dritten Parameter zu verwenden, der den Schlüsselnamen des zurückgegebenen Fehlers darstellt.

Aktualisiert am 6. Dezember 2016 (v2.2.4)

Vollständiges Beispiel: https://embed.plnkr.co/ukwCXm/

cyber_dave
quelle
@ Dave << mit nicht mehreren Gruppen >> Meinten Sie eigentlich << mit mehreren Gruppen >> oder was? Danke
Superjos
Dies scheint nicht die Warnung Markup zu entfernen , wenn die Passwörter mit kantigen 2 RC.1 entsprechen
datatype_void
"ControlGroups" scheint in 2.0 nicht zu existieren. Ich habe 'FormGroup'
Stephen
@superjos Das wollte ich sagen. Einige Entwickler entscheiden sich dafür, ein verschachteltes Element FormGroupfür die Validierung mehrerer Felder zu erstellen, anstatt Validatordas Ganze zu aktivieren.
Cyber_Dave
1
Was ist, wenn wir Passwort, Bestätigungspasswort und E-Mail haben und E-Mail bestätigen? [{validator: matchingPasswords('password', 'confirmPassword')},{validator: matchingEmail('email', 'confirmemail')}] Ich habe es versucht, aber es funktioniert nicht. Irgendwelche Vorschläge ? @ Dave
Sharan Ainapurapu
51

Daves Antwort war sehr, sehr hilfreich. Eine geringfügige Änderung kann jedoch einigen Personen helfen.

Falls Sie den ControlFeldern Fehler hinzufügen müssen, können Sie die tatsächliche Konstruktion des Formulars und der Validatoren beibehalten:

// Example use of FormBuilder, ControlGroups, and Controls
this.registrationForm= fb.group({
  dob: ['', Validators.required],
  email: ['', Validators.compose([Validators.required,  emailValidator])],
  password: ['', Validators.required],
  confirmPassword: ['', Validators.required],
  firstName: ['', Validators.required],
  lastName: ['', Validators.required]
}, {validator: matchingPasswords('password', 'confirmPassword')})

Anstatt einen Fehler für das ControlGroupFeld festzulegen, gehen Sie wie folgt für das tatsächliche Feld vor:

function matchingPasswords(passwordKey: string, passwordConfirmationKey: string) {
  return (group: ControlGroup) => {
    let passwordInput = group.controls[passwordKey];
    let passwordConfirmationInput = group.controls[passwordConfirmationKey];
    if (passwordInput.value !== passwordConfirmationInput.value) {
      return passwordConfirmationInput.setErrors({notEquivalent: true})
    }
  }
}
Louis Cruz
quelle
6
Verwenden Sie diese Option passwordConfirmationInput.setErrors(passwordConfirmationInput.validator(passwordConfirmationInput))in der elseVerzweigung, um sie korrekt zu aktualisieren, wenn eine Änderung an passwordInputdie Daten gültig macht.
andraaspar
@andraaspar Ich habe das versucht, aber ich habe den Fehler bekommen TypeError: passwordConfirmationInput.validator is not a function. Dies liegt daran, dass ich das FormControl nicht explizit mit Validators.required erstellt habe. Ich habe die Validatoren leer gelassen und stattdessen das Attribut "erforderlich" für die Eingabe verwendet.
Bartlinuxgeek
6
Dies war hilfreich, aber ich habe festgestellt, dass die eckige Dokumentation einen Rückgabetyp hat {[key: string]: any}, der setErrors(...)(nicht mehr?) Nicht zurückgibt. Auch setErrors(...)überschreibt alle Fehler , die bereits vorhanden sind, so dass ich auf die aktuelle Fehlerobjekt angehängt wie: let errors = formGroup.controls[passwordConfirmationKey].errors;und if(!errors) errors={};und errors['notEquivalent'] = true;undformGroup.controls[dateControlFirst].setErrors(errors);
Stephen
32

Wenn Sie Validatoren für mehrere Formularfelder implementieren, müssen Sie sicherstellen, dass Validatoren neu bewertet werden, wenn jedes Formularsteuerelement aktualisiert wird. Die meisten Beispiele bieten keine Lösung für ein solches Szenario, dies ist jedoch sehr wichtig für die Datenkonsistenz und das korrekte Verhalten.

Weitere Informationen finden Sie in meiner Implementierung eines benutzerdefinierten Validators für Angular 2, der dies berücksichtigt: https://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30 .

Ich verwende otherControl.valueChanges.subscribe(), um auf Änderungen in anderen Steuerelementen thisControl.updateValueAndValidity()zu warten und eine weitere Validierungsrunde auszulösen, wenn andere Steuerelemente geändert werden.


Ich kopiere einen Code unten, um später darauf zurückgreifen zu können:

match-other-validator.ts

import {FormControl} from '@angular/forms';


export function matchOtherValidator (otherControlName: string) {

  let thisControl: FormControl;
  let otherControl: FormControl;

  return function matchOtherValidate (control: FormControl) {

    if (!control.parent) {
      return null;
    }

    // Initializing the validator.
    if (!thisControl) {
      thisControl = control;
      otherControl = control.parent.get(otherControlName) as FormControl;
      if (!otherControl) {
        throw new Error('matchOtherValidator(): other control is not found in parent group');
      }
      otherControl.valueChanges.subscribe(() => {
        thisControl.updateValueAndValidity();
      });
    }

    if (!otherControl) {
      return null;
    }

    if (otherControl.value !== thisControl.value) {
      return {
        matchOther: true
      };
    }

    return null;

  }

}

Verwendung

So können Sie es mit reaktiven Formen verwenden:

private constructForm () {
  this.form = this.formBuilder.group({
    email: ['', [
      Validators.required,
      Validators.email
    ]],
    password: ['', Validators.required],
    repeatPassword: ['', [
      Validators.required,
      matchOtherValidator('password')
    ]]
  });
}

Weitere aktuelle Validatoren finden Sie hier: moebius-mlm / ng-validatoren .

Slava Fomin II
quelle
Gute Antwort!! Ich habe stundenlang nach einer solchen Lösung gesucht! Bitte beachten Sie eine kleine Änderung: Anstatt "diese" Referenz bei der Rückgabe einer Funktion zu verlieren, geben Sie eine Funktion wie die folgende zurück: return (control: FormControl) => {/ * code * /}
Vingtoft
Froh, dass ich helfen konnte. Warum brauchen Sie einen Verweis auf thisfür? Eigentlich ist es gut, eine benannte Funktion für Debugging-Zwecke zu haben.
Slava Fomin II
Performance? Es funktioniert, aber in Bezug auf die Leistung halte ich es nicht für eine gute Lösung. Wenn Sie 'thisControl' aktualisieren, wenn der Wert von 'theOtherControl geändert wird, wird eine Schleife erstellt, nicht wahr?
NachtElf91
Wann sollte es abbestellt werden? othercontrol.valuechanges.subscribewurde nirgendwo abgemeldet.
Juana Pu
@juanapu Ich würde davon ausgehen, dass Angular das valueChangesObservable beendet, wenn das otherControlzerstört wird, was dazu führt, dass das Abonnement ebenfalls beendet wird. Ihre Bedenken könnten jedoch berechtigt sein. Ich würde vorschlagen, diesen Code mit der neuesten Version von Angular unter Verwendung verschiedener Testfälle gründlich zu debuggen. Bitte melden Sie sich zurück, wenn Sie Probleme finden.
Slava Fomin II
23

Ich verwende Angular 2 RC.5, konnte aber die ControlGroup aufgrund der hilfreichen Antwort von Dave nicht finden. Ich fand, dass FormGroup stattdessen funktioniert. Also habe ich ein paar kleinere Updates für Daves Codes gemacht und dachte, ich würde sie mit anderen teilen.

Fügen Sie in Ihrer Komponentendatei einen Import für FormGroup hinzu:

import {FormGroup} from "@angular/forms";

Definieren Sie Ihre Eingaben, falls Sie direkt auf das Formularsteuerelement zugreifen müssen:

oldPassword = new FormControl("", Validators.required);
newPassword = new FormControl("", Validators.required);
newPasswordAgain = new FormControl("", Validators.required);

Instanziieren Sie in Ihrem Konstruktor Ihr Formular:

this.form = fb.group({
  "oldPassword": this.oldPassword,
  "newPassword": this.newPassword,
  "newPasswordAgain": this.newPasswordAgain
}, {validator: this.matchingPasswords('newPassword', 'newPasswordAgain')});

Fügen Sie die MatchingPasswords-Funktion in Ihre Klasse ein:

matchingPasswords(passwordKey: string, passwordConfirmationKey: string) {
  return (group: FormGroup) => {
    let passwordInput = group.controls[passwordKey];
    let passwordConfirmationInput = group.controls[passwordConfirmationKey];
    if (passwordInput.value !== passwordConfirmationInput.value) {
      return passwordConfirmationInput.setErrors({notEquivalent: true})
    }
  }
}

Hoffe, dies hilft denen, die RC.5 verwenden. Beachten Sie, dass ich noch nicht auf RC.6 getestet habe.

Chang
quelle
@Sam Hast du etwas geändert, damit es mit der endgültigen Version funktioniert? es funktioniert nicht für mich .. Es heißt: Argument vom Typ '{validator: (group: FormGroup) => void; } 'kann keinem Parameter vom Typ' ValidatorFn 'zugewiesen werden.
xtof
Nein, ich musste nichts ändern - für mich funktionierte der obige Beispielcode mit Angular2 final. Verwenden Sie den genauen Code wie oben?
Sam
Gute Lösung @Chang. Wenn Sie Ihr Passwort ändern, nachdem Sie Ihr Passwort bestätigt haben. Die Validierung funktioniert nicht. Sie können versuchenif (passwordInput.value !== passwordConfirmationInput.value) { return passwordConfirmationInput.setErrors({ notEquivalent: true }); } else { return passwordConfirmationInput.setErrors(null); }
Mario Shtika
16

Viel Graben in eckigen Quellen, aber ich habe einen besseren Weg gefunden.

constructor(...) {
    this.formGroup = builder.group({
        first_name:        ['', Validators.required],
        matching_password: builder.group({
            password: ['', Validators.required],
            confirm:  ['', Validators.required]
        }, this.matchPassword)
    });

    // expose easy access to passworGroup to html
    this.passwordGroup = this.formGroup.controls.matching_password;
}

matchPassword(group): any {
    let password = group.controls.password;
    let confirm = group.controls.confirm;

    // Don't kick in until user touches both fields   
    if (password.pristine || confirm.pristine) {
      return null;
    }

    // Mark group as touched so we can add invalid class easily
    group.markAsTouched();

    if (password.value === confirm.value) {
      return null;
    }

    return {
      isValid: false
    };
}

HTML-Teil für Passwortgruppe

<div ng-control-group="matching_password" [class.invalid]="passwordGroup.touched && !passwordGroup.valid">
    <div *ng-if="passwordGroup.touched && !passwordGroup.valid">Passwords must match.</div>
    <div class="form-field">
        <label>Password</label>
        <input type="password" ng-control="password" placeholder="Your password" />
    </div>
    <div class="form-field">
        <label>Password Confirmation</label>
        <input type="password" ng-control="confirm" placeholder="Password Confirmation" />
    </div>
</div>
matthewdaniel
quelle
Wenn die Validierung für matching_password ausgeführt wird, wird auch das Steuerelement firstName ausgewertet? Was ich nicht wollen würde!
Pascal
16

Die Antwort von matthewdaniel erweitern, da sie nicht genau richtig ist. Hier ist ein Beispielcode, der zeigt, wie ein Validator einem richtig zugewiesen wird ControlGroup.

import {Component} from angular2/core
import {FormBuilder, Control, ControlGroup, Validators} from 'angular2/common'

@Component({
  selector: 'my-app',
  template: `
    <form [ngFormModel]="form">
      <label for="name">Name:</label>
      <input id="name" type="text" ngControl="name">
      <br>
      <label for="email">Email:</label>
      <input id="email" type="email" ngControl="email">
      <br>
      <div ngControlGroup="matchingPassword">
        <label for="password">Password:</label>
        <input id="password" type="password" ngControl="password">
        <br>
        <label for="confirmPassword">Confirm Password:</label>
        <input id="confirmPassword" type="password" ngControl="confirmPassword">
      </div>
    </form>
    <p>Valid?: {{form.valid}}</p>
    <pre>{{form.value | json}}</pre>
  `
})
export class App {
  form: ControlGroup
  constructor(fb: FormBuilder) {
    this.form = fb.group({
      name: ['', Validators.required],
      email: ['', Validators.required]
      matchingPassword: fb.group({
        password: ['', Validators.required],
        confirmPassword: ['', Validators.required]
      }, {validator: this.areEqual})
    });
  }

  areEqual(group: ControlGroup) {
    let val;
    let valid = true;

    for (name in group.controls) {
      if (val === undefined) {
        val = group.controls[name].value
      } else {
        if (val !== group.controls[name].value) {
          valid = false;
          break;
        }
      }
    }

    if (valid) {
      return null;
    }

    return {
      areEqual: true
    };
  }
}

Hier ist ein funktionierendes Beispiel: http://plnkr.co/edit/Zcbg2T3tOxYmhxs7vaAm?p=preview

Cody L.
quelle
Was ist, wenn wir Radiobuttons und ein Kontrollkästchen hinzufügen, um den Wert dieser beiden zu ermitteln?
Pardeep Jain
2
ControlGroupwird zugunsten eines FormGroupBetrachters entfernt. Docs and Learn Angular2 Beispiel
leise
2

Hier ist eine weitere Option, die ich mir ausgedacht habe und die nicht von einem Ganzen oder Sub abhängig ControlGroupist, sondern direkt an jedes gebunden ist Control.

Das Problem, das ich hatte, war, dass die Steuerelemente, die voneinander abhängig waren, nicht hierarchisch zusammen waren, sodass ich keine erstellen konnte ControlGroup. Außerdem wurde mein CSS so eingerichtet, dass jedes Steuerelement die vorhandenen Winkelklassen nutzt, um zu bestimmen, ob ein Fehlerstil angezeigt werden soll. Dies war komplizierter, wenn eine Gruppenvalidierung anstelle einer steuerungsspezifischen Validierung durchgeführt wurde. Der Versuch festzustellen, ob eine einzelne Kontrolle gültig war, war nicht möglich, da die Validierung an die Gruppe von Kontrollen und nicht an jede einzelne Kontrolle gebunden war.

In meinem Fall wollte ich, dass der Wert eines Auswahlfelds bestimmt, ob ein anderes Feld erforderlich ist oder nicht.

Dies wird mit dem Form Builder für die Komponente erstellt. Für das ausgewählte Modell habe ich es nicht direkt an den Wert des Anforderungsobjekts gebunden, sondern an Funktionen zum Abrufen / Festlegen gebunden, mit denen ich Ereignisse "bei Änderung" für das Steuerelement verarbeiten kann. Dann kann ich die Validierung für ein anderes Steuerelement manuell festlegen, abhängig vom neuen Wert der ausgewählten Steuerelemente.

Hier ist der relevante Ansichtsteil:

<select [ngFormControl]="form.controls.employee" [(ngModel)]="employeeModel">
  <option value="" selected></option>
  <option value="Yes">Yes</option>
  <option value="No">No</option>
</select>
...
<input [ngFormControl]="form.controls.employeeID" type="text" maxlength="255" [(ngModel)]="request.empID" />

Der relevante Komponententeil:

export class RequestComponent {
  form: ControlGroup;
  request: RequestItem;

  constructor(private fb: FormBuilder) {
      this.form = fb.group({
        employee: new Control("", Validators.required),
        empID: new Control("", Validators.compose([Validators.pattern("[0-9]{7}"]))
      });

  get employeeModel() {
    return this.request.isEmployee;
  }

  set employeeModel(value) {
    this.request.isEmployee = value;
    if (value === "Yes") {
      this.form.controls["empID"].validator = Validators.compose([Validators.pattern("[0-9]{7}"), Validators.required]);
      this.form.controls["empID"].updateValueAndValidity();
    }
    else {
      this.form.controls["empID"].validator = Validators.compose([Validators.pattern("[0-9]{7}")]);
      this.form.controls["empID"].updateValueAndValidity();
    }
  }
}

In meinem Fall war immer eine Mustervalidierung an das Steuerelement gebunden, sodass das validatorimmer auf etwas gesetzt ist, aber ich denke, Sie können das validatorauf null setzen, wenn Sie keine Validierung an das Steuerelement gebunden haben.

UPDATE: Es gibt andere Methoden zum Erfassen der (ngModelChange)=changeFunctionName($event)Modelländerung, z. B. zum Abonnieren von Steuerwertänderungen mithilfe vonthis.form.controls["employee"].valueChanges.subscribe(data => ...))

Daniel Sara
quelle
1

equalToIch habe auch danach gesucht und am Ende das ng2-Validierungspaket ( https://www.npmjs.com/package/ng2-validation ) verwendet.

Hier ist ein Beispiel: Template Driven:

<input type="password" ngModel name="password" #password="ngModel" required/>
<p *ngIf="password.errors?.required">required error</p>
<input type="password" ngModel name="certainPassword" #certainPassword="ngModel" [equalTo]="password"/>
<p *ngIf="certainPassword.errors?.equalTo">equalTo error</p>

Modellgetrieben:

let password = new FormControl('', Validators.required);
let certainPassword = new FormControl('', CustomValidators.equalTo(password));

this.form = new FormGroup({
  password: password,
  certainPassword: certainPassword
});

Vorlage:

<form [formGroup]="form">
  <input type="password" formControlName="password"/>
  <p *ngIf="form.controls.password.errors?.required">required error</p>
  <input type="password" formControlName="certainPassword"/>
  <p *ngIf="form.controls.certainPassword.errors?.equalTo">equalTo error</p>
</form>
Baidaly
quelle
1

Hier ist meine Version, die ich verwendet habe, um sicherzustellen, dass ein Alter in einem Feld größer oder gleich dem Alter in einem anderen Feld ist. Ich verwende auch Formulargruppen, daher verwende ich die group.getFunktion eher alsgroup.controls[]

import { FormGroup } from '@angular/forms';

export function greaterThanOrEqualTo(sourceKey: string, targetKey: string) {
    return (group: FormGroup) => {
        let sourceInput = group.get(sourceKey);
        let targetInput = group.get(targetKey);

        console.log(sourceInput);
        console.log(targetInput);

        if (targetInput.value < sourceInput.value) {
            return targetInput.setErrors({ notGreaterThanOrEqualTo: true })
        }
    }
}

Und in der Komponente:

    this.form = this._fb.group({

        clientDetails: this._fb.group({
            currentAge: ['', [Validators.required, Validators.pattern('^((1[89])|([2-9][0-9])|100)$')]],
            expectedRetirementAge: ['', [Validators.required]]
        }),

    },
    {
        validator: greaterThanOrEqualTo('clientDetails.currentAge', 'clientDetails.expectedRetirementAge')
    });
Adam Hockemeyer
quelle
0

Ich denke, Ihre beste Wette für den Moment ist es, eine Formulargruppe zu erstellen, die Ihre Steuerelemente enthält. Wenn Sie Ihren Control-Instanziieren, übergeben Sie die Funktion, um ihn zu validieren. Beispiel:

    this.password = new Control('', Validators.required);
    let x = this.password;
    this.confirm = new Control('', function(c: Control){
        if(typeof c.value === 'undefined' || c.value == "") return {required: "password required"};
        if(c.value !== x.value)
            return {error: "password mismatch"};
        return null;
    });

Ich weiß, dass dies stark von der Version von anglejs2 abhängt, die Sie ausführen. Dies wurde gegen 2.0.0-alpha.46 getestet

Wenn jemand einen besseren Vorschlag hat, z. B. einen benutzerdefinierten Validator zu schreiben (was möglicherweise der beste Weg ist), ist er willkommen.

BEARBEITEN

Sie können auch ControlGroup verwenden und diese Gruppe vollständig validieren.

this.formGroup = new ControlGroup({}, function(c: ControlGroup){
        var pass: Control = <Control>c.controls["password"];
        var conf: Control = <Control>c.controls["confirm"];
        pass.setErrors(null, true);
        if(pass.value != null && pass.value != ""){
            if(conf.value != pass.value){
                pass.setErrors({error: "invalid"}, true);
                return {error: "error"};
            }
        }
        return null;
    });

Bearbeiten Sie einfach die Nachrichten entsprechend Ihrer Domain.

Bruno Pires Lavigne Quintanilh
quelle
0

Die Antwort von Louis Cruz war für mich sehr hilfreich.

Zum Abschluss fügen Sie einfach das Zurücksetzen der setErrors hinzu: return passwordConfirmationInput.setErrors (null);

Und alles funktioniert gut!

Danke,

Grüße,

TGA

TGA
quelle
0

Winkel 8 Beispiel für die Validierung im Kennwortbestätigungsfeld

Zu Ihrer Information: Dadurch wird die Validierung im Feld passwordConfirm nicht aktualisiert, wenn das Hauptfeld "password" nach Ablauf dieser Validierung geändert wird. Sie können das Kennwortbestätigungsfeld jedoch ungültig machen, wenn ein Benutzer in das Kennwortfeld eingibt

<input
  type="password"
  formControlName="password"
  (input)="registerForm.get('passwordConfirm').setErrors({'passwordMatches': true})"
/>

register.component.ts

import { PasswordConfirmValidator } from './password-confirm-validator';
export class RegisterComponent implements OnInit {
  registerForm: FormGroup = this.createRegisterForm({
    username: new FormControl('', [Validators.required, Validators.email]),
    password: new FormControl('', [
      Validators.required,
      Validators.pattern('^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$'),
      Validators.minLength(8)
    ]),
    passwordConfirm: new FormControl('', [
      Validators.required,
      PasswordConfirmValidator //custom validator
    ])
  });
}

Passwort-Bestätigungs-Validator.ts

import { AbstractControl } from '@angular/forms';

export function PasswordConfirmValidator(control: AbstractControl) {
  if(void 0 === control){ return null; }
  if(
    void 0 !== control.parent &&
    void 0 !== control.parent.controls &&
    void 0 !== control.parent.controls['password'] &&
    control.parent.controls['password'].value === control.value
  ){
    return null;
  }
  return {passwordMatches: true};
}

register.component.html

{{registerForm.get('passwordConfirm').hasError('passwordMatches')}}
Tim Joyce
quelle
-2

Ich würde vorschlagen, die Bibliothek zu benutzen ng-form-rules. Es ist eine großartige Bibliothek zum Erstellen aller Arten von Formularen mit von der Komponente entkoppelter Validierungslogik, die von Wertänderungen anderer Bereiche im Formular abhängen kann. Sie haben eine großartige Dokumentation , Beispiele und ein Video, das eine Reihe seiner Funktionen zeigt . Eine solche Validierung durchzuführen ist trivial.

In der README-Datei finden Sie einige allgemeine Informationen und ein einfaches Beispiel.

Chris Knight
quelle
2
Ich mag die Idee nicht, dass es für alles eine Bibliothek gibt ... Bibliotheken sind nicht die Lösung für dieses Problem. Oft verursachen Sie neue Probleme, wenn Sie nur eine andere Bibliothek verwenden. Außerdem müssen Sie die Inhalte bei Angular-Updates auf dem neuesten Stand halten. Warum nicht eckige Formen verwenden, wie es das Framework vorsieht?
Nadine
-3

Validierungsregeln für Angular 4-Kennwortübereinstimmungen.

Wenn Sie Fehlerkontrollfelder benötigen, können Sie dies tun.

createForm() {
    this.ngForm = this.fb.group({
       'first_name': ["", Validators.required ],
       'last_name' : ["", Validators.compose([Validators.required, Validators.minLength(3)]) ],
       'status' : ['active', Validators.compose([Validators.required])],
       'phone':[null],
       'gender':['male'],
       'address':[''],
       'email':['', Validators.compose([
          Validators.required, 
          Validators.email])],
       'password':['', Validators.compose([Validators.required])],
       'confirm_password':['', Validators.compose([Validators.required])]
    }, {validator: this.matchingPassword('password', 'confirm_password')});
  }

Dann müssen Sie diese Methode in constructorMethode Like as deklarieren.

constructor(
    private fb: FormBuilder

    ) {
    this.createForm();
  }

Anstatt einen Fehler in der ControlGroup festzulegen, gehen Sie im eigentlichen Feld wie folgt vor:

    matchingPassword(passwordKey: string, confirmPasswordKey: string) {
  return (group: FormGroup): {[key: string]: any} => {
    let password = group.controls[passwordKey];
    let confirm_password = group.controls[confirmPasswordKey];

    if (password.value !== confirm_password.value) {
      return {        
        mismatchedPasswords: true
      };
    }
  }
}

HTML-Teil für Passwortgruppe

<form [formGroup]="ngForm" (ngSubmit)="ngSubmit()">
    <div class="form-group">
            <label class="control-label" for="inputBasicPassword"> Password <span class="text-danger">*</span></label>
                <input type="password" class="form-control" formControlName="password" placeholder="Password" name="password" required>
                <div class="alert text-danger" *ngIf="!ngForm.controls['password'].valid && ngForm.controls['password'].touched">This Field is Required.</div>
            </div>
            {{ngForm.value.password | json}}
            <div class="form-group">
            <label class="control-label" for="inputBasicPassword">Confirm Password <span class="text-danger">*</span></label>
                <input type="password" class="form-control" name="confirm_password" formControlName="confirm_password" placeholder="Confirm Password" match-password="password">

    <div class='alert text-danger' *ngIf="ngForm.controls.confirm_password.touched && ngForm.hasError('mismatchedPasswords')">
              Passwords doesn't match.
      </div>
    </div>
<button type="submit" [disabled]="!ngForm.valid" class="btn btn-primary ladda-button" data-plugin="ladda" data-style="expand-left" disabled="disabled"><span class="ladda-label">
            <i class="fa fa-save"></i>  Create an account
        <span class="ladda-spinner"></span><div class="ladda-progress" style="width: 0px;"></div>
        </span><span class="ladda-spinner"></span></button>
</form>
Md.Jewel Mia
quelle