Validateur Angular2 qui repose sur plusieurs champs de formulaire


118

Est-il possible de créer un validateur qui peut utiliser plusieurs valeurs pour décider si mon champ est valide?

Par exemple, si la méthode de contact préférée du client est par e-mail, le champ e-mail doit être obligatoire.

Merci.


Mis à jour avec un exemple de code ...


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

    }

Oui. Et si vous nous montrez votre code, nous pourrions ajouter une réponse spécifique.
michelem

J'ai ajouté un exemple de base. Dans l'exemple de code, comment puis-je valider le code postal uniquement si le contrôle validateZip précédent contient «oui»?
Simon

Simon, pourquoi ne pas promouvoir la réponse à votre question?
superjos

6
Ok, pour éviter beaucoup de frustration aux futurs visiteurs de cette question, je recommande fortement d'utiliser ce package NPM: npmjs.com/package/ng2-validation . Il a intégré equal, des equalTométhodes et une bonne documentation!
Michelangelo

Réponses:


147

Pour répéter les méthodes que d'autres ont publiées, c'est ainsi que j'ai créé FormGroup validateurs qui n'impliquent pas plusieurs groupes.

Pour cet exemple, fournissez simplement les noms de clé des champs passwordet 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')})

Pour Validatorsprendre des paramètres, ils doivent renvoyer a functionavec a FormGroupou FormControlcomme paramètre. Dans ce cas, je valide un fichier 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
      };
    }
  }
}

Techniquement, j'aurais pu valider deux valeurs si je connaissais leurs clés, mais je préfère nommer mon Validators la même manière que l'erreur qu'elles renverront. La fonction peut être modifiée pour prendre un troisième paramètre qui représente le nom de clé de l'erreur renvoyée.

Mise à jour le 6 décembre 2016 (v2.2.4)

Exemple complet: https://embed.plnkr.co/ukwCXm/


@Dave << qui n'implique pas plusieurs groupes >> Vouliez-vous dire << qui impliquent plusieurs groupes >>, ou quoi? Merci
superjos

Cela ne semble pas supprimer le balisage d'alerte lorsque les mots de passe correspondent à Angular 2 RC.1
datatype_void

"ControlGroups" ne semble pas exister dans 2.0. J'ai utilisé 'FormGroup'
Stephen

@superjos Je voulais dire ça. Certains développeurs choisissent de créer un imbriqué FormGrouppour gérer la validation multi-champs au lieu de mettre un Validatorsur le tout.
cyber_dave

1
Et si nous avons un mot de passe, confirmez le mot de passe et un e-mail et confirmez l'e-mail? [{validator: matchingPasswords('password', 'confirmPassword')},{validator: matchingEmail('email', 'confirmemail')}] J'ai essayé cela mais cela ne fonctionne pas. Aucune suggestion ? @Dave
Sharan Ainapurapu

51

La réponse de Dave a été très, très utile. Cependant, une légère modification pourrait aider certaines personnes.

Au cas où vous auriez besoin d'ajouter des erreurs dans les Controlchamps, vous pouvez conserver la construction réelle du formulaire et des validateurs:

// 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')})

Au lieu de définir une erreur sur le ControlGroup, faites-le sur le champ réel comme suit:

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

6
Utilisez passwordConfirmationInput.setErrors(passwordConfirmationInput.validator(passwordConfirmationInput))dans la elsebranche pour la mettre à jour correctement lorsqu'une modification de passwordInputrend les données valides.
andraaspar le

@andraaspar J'ai essayé mais j'ai eu l'erreur TypeError: passwordConfirmationInput.validator is not a function. C'est parce que je n'ai pas créé explicitement le FormControl avec Validators.required. J'ai laissé les validateurs vides et utilisé à la place l'attribut "requis" sur l'entrée.
beardedlinuxgeek

6
Cela a été utile, mais j'ai remarqué que la documentation angulaire a un type de retour {[key: string]: any}, qui setErrors(...)ne retourne pas (plus?). setErrors(...)Ecrase également toutes les erreurs déjà présentes, j'ai donc ajouté à l'objet d'erreur actuel comme: let errors = formGroup.controls[passwordConfirmationKey].errors;and if(!errors) errors={};and errors['notEquivalent'] = true;andformGroup.controls[dateControlFirst].setErrors(errors);
Stephen

32

Lors de l'implémentation de validateurs pour plusieurs champs de formulaire, vous devrez vous assurer que les validateurs sont réévalués lorsque chacun des contrôles de formulaire est mis à jour. La plupart des exemples ne fournissent pas de solution pour un tel scénario, mais cela est très important pour la cohérence des données et un comportement correct.

Veuillez consulter mon implémentation d'un validateur personnalisé pour Angular 2, qui en tient compte: https://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30 .

J'utilise otherControl.valueChanges.subscribe()pour écouter les changements dans un autre contrôle et thisControl.updateValueAndValidity()pour déclencher un autre cycle de validation lorsque l'autre contrôle est modifié.


Je copie un code ci-dessous pour référence future:

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;

  }

}

Usage

Voici comment vous pouvez l'utiliser avec des formulaires réactifs:

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

Des validateurs plus à jour peuvent être trouvés ici: moebius-mlm / ng-validators .


Bonne réponse!! Je cherchais une solution comme celle-ci depuis des heures! Veuillez considérer un petit changement: au lieu de perdre "cette" référence lors du retour d'une fonction, renvoyez une fonction comme celle-ci: return (control: FormControl) => {/ * code * /}
Vingtoft

Heureux d'avoir pu aider. Pourquoi avez-vous besoin de référence thispour? En fait, il est bon d'avoir une fonction nommée à des fins de débogage.
Slava Fomin II

Performance? cela fonctionne mais en termes de performances, je ne pense pas que ce soit une bonne solution. La mise à jour de 'thisControl' lorsque la valeur de 'theOtherControl est modifiée créera une boucle, n'est-ce pas?
nightElf91

Quand faut-il se désinscrire? othercontrol.valuechanges.subscribene s'est désabonné nulle part.
juana pu

@juanapu Je suppose qu'Angular mettra fin à l' valueChangesobservable lorsque celui- otherControlci sera détruit, ce qui entraînera également la résiliation de l'abonnement. Cependant, vos préoccupations pourraient être valables. Je suggérerais de déboguer complètement ce code avec la dernière version d'Angular en utilisant divers cas de test. S'il vous plaît, faites un rapport si vous trouvez des problèmes.
Slava Fomin II

23

J'utilise Angular 2 RC.5 mais je n'ai pas trouvé le ControlGroup, basé sur la réponse utile de Dave. J'ai trouvé que FormGroup fonctionne à la place. J'ai donc fait quelques mises à jour mineures sur les codes de Dave et j'ai pensé partager avec d'autres.

Dans votre fichier de composant, ajoutez une importation pour FormGroup:

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

Définissez vos entrées au cas où vous auriez besoin d'accéder directement au contrôle de formulaire:

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

Dans votre constructeur, instanciez votre formulaire:

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

Ajoutez la fonction matchingPasswords dans votre classe:

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

J'espère que cela aidera ceux qui utilisent RC.5. Notez que je n'ai pas encore testé sur RC.6.


@Sam Avez-vous changé quelque chose pour qu'il fonctionne avec la version finale? ça ne marche pas pour moi .. Il dit: Argument de type '{validator: (group: FormGroup) => void; } 'n'est pas attribuable au paramètre de type' ValidatorFn '.
xtof le

Non, je n'ai rien changé - pour moi, l'exemple de code ci-dessus fonctionnait avec Angular2 final. Utilisez-vous le code exact comme ci-dessus?
Sam

Bonne solution @Chang. Si vous modifiez votre mot de passe après avoir rempli votre mot de passe de confirmation. La validation ne fonctionne pas. Vous pouvez essayerif (passwordInput.value !== passwordConfirmationInput.value) { return passwordConfirmationInput.setErrors({ notEquivalent: true }); } else { return passwordConfirmationInput.setErrors(null); }
Mario Shtika

16

Beaucoup de creuser dans la source angulaire mais j'ai trouvé un meilleur moyen.

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

Partie HTML pour le groupe de mots de passe

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

Lorsque la validation de matching_password est exécutée, le contrôle firstName est-il également évalué? Ce que je ne voudrais pas!
Pascal

16

Pour développer la réponse de matthewdaniel car ce n'est pas tout à fait correct. Voici un exemple de code qui montre comment attribuer correctement un validateur à un fichier 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
    };
  }
}

Voici un exemple fonctionnel: http://plnkr.co/edit/Zcbg2T3tOxYmhxs7vaAm?p=preview


et si nous ajoutons des boutons radio et une case à cocher comment obtenir la valeur de ces deux?
Pardeep Jain

2
ControlGroupest supprimé au profit de FormGrouppour quiconque regarde cela. Exemple Docs and Learn Angular2
doucement

2

Voici une autre option que j'ai pu proposer qui ne dépend pas d'un sous-ensemble ou d'un sous-marin ControlGroupmais est directement liée à chacun Control.

Le problème que j'avais était que les contrôles qui dépendaient les uns des autres n'étaient pas hiérarchiquement ensemble, donc je n'ai pas pu créer un fichier ControlGroup. De plus, mon CSS a été configuré pour que chaque contrôle exploite les classes angulaires existantes pour déterminer s'il faut afficher le style d'erreur, ce qui était plus compliqué lorsqu'il s'agissait d'une validation de groupe au lieu d'une validation spécifique au contrôle. Essayer de déterminer si un seul contrôle était valide n'était pas possible puisque la validation était liée au groupe de contrôles et non à chaque contrôle individuel.

Dans mon cas, je voulais la valeur d'une boîte de sélection pour déterminer si un autre champ serait requis ou non.

Ceci est construit à l'aide du générateur de formulaires sur le composant. Pour le modèle de sélection au lieu de le lier directement à la valeur de l'objet de requête, je l'ai lié pour obtenir / définir des fonctions qui me permettront de gérer les événements "sur modification" pour le contrôle. Ensuite, je pourrai définir manuellement la validation d'un autre contrôle en fonction de la nouvelle valeur des contrôles de sélection.

Voici la partie de la vue pertinente:

<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" />

La partie composante pertinente:

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

Dans mon cas, j'ai toujours eu une validation de modèle liée au contrôle, donc le validatorest toujours défini sur quelque chose, mais je pense que vous pouvez définir le validatorsur null si vous n'avez aucune validation liée au contrôle.

MISE À JOUR: Il existe d'autres méthodes pour capturer le changement de modèle comme (ngModelChange)=changeFunctionName($event)ou souscrire pour contrôler les changements de valeur en utilisantthis.form.controls["employee"].valueChanges.subscribe(data => ...))



1

Je cherchais également cela et a fini par utiliser le equalTopackage ng2-validation ( https://www.npmjs.com/package/ng2-validation )

Voici un exemple: Piloté par un modèle:

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

Modèle conduit:

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

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

Modèle:

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

1

Voici ma version que j'ai utilisée pour m'assurer qu'un âge dans un domaine est supérieur ou égal à l'âge dans un autre domaine. J'utilise également des groupes de formulaires, donc j'utilise la group.getfonction plutôt quegroup.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 })
        }
    }
}

Et dans le composant:

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

0

Je pense que votre meilleur pari, pour l'instant, est de créer un groupe de formulaires pour tenir vos commandes. Lorsque vous instanciez votre passe de contrôle dans la fonction pour la valider. exemple:

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

Je sais que cela dépend fortement de la version d'angularjs2 que vous utilisez. Cela a été testé contre 2.0.0-alpha.46

Si quelqu'un a une meilleure suggestion telle que l'écriture d'un validateur personnalisé (ce qui peut être la meilleure façon de procéder), c'est le bienvenu.

ÉDITER

vous pouvez également utiliser ControlGroup et valider ce groupe dans son intégralité.

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

Modifiez simplement les messages en fonction de votre domaine.


0

La réponse de Louis Cruz m'a été très utile.

Pour terminer, ajoutez simplement dans le else la réinitialisation de setErrors: return passwordConfirmationInput.setErrors (null);

Et tout fonctionne bien!

Merci,

Cordialement,

TGA


0

Angular 8 Exemple de validation sur le champ de confirmation du mot de passe

FYI: cela ne mettra pas à jour la validation sur le champ passwordConfirm si le champ principal "mot de passe" est changé après que cette validation soit passée. Mais, vous pouvez invalider le champ de confirmation du mot de passe lorsqu'un utilisateur tape dans le champ du mot de passe

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

password-confirm-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')}}

-2

Je suggérerais d'utiliser la bibliothèque ng-form-rules . C'est une bibliothèque géniale pour créer tous les types de formulaires avec une logique de validation découplée du composant et qui peut dépendre des changements de valeur d'autres zones du formulaire. Ils ont une excellente documentation , des exemples et une vidéo qui montre un tas de ses fonctionnalités . Faire une validation comme celle-ci, ce que vous essayez de faire est trivial.

Vous pouvez consulter leur README pour des informations de haut niveau et un exemple de base.


2
Je n'aime pas l'idée qu'il y ait une bibliothèque pour tout ... les bibliothèques ne sont pas la solution à ce problème. Souvent, vous créerez de nouveaux problèmes en utilisant simplement une autre bibliothèque, vous devez également garder le contenu à jour lorsque Angular se met à jour. Pourquoi ne pas utiliser des formes angulaires comme prévu par le cadre?
Nadine

-3

Règles de validation de correspondance de mot de passe angulaire 4.

Si vous avez besoin de champs de contrôle des erreurs, vous pouvez le faire.

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

Ensuite, vous devez déclarer cette méthode dans la constructorméthode Like as.

constructor(
    private fb: FormBuilder

    ) {
    this.createForm();
  }

Au lieu de définir une erreur sur le ControlGroup, procédez comme suit sur le champ réel:

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

Partie HTML pour le groupe de mots de passe

<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>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.