web-dev-qa-db-fra.com

mot de passe et confirmation du champ de mot de passe validation des formulaires angular2 réactifs

Je dois vérifier si le mot de passe et confirmer les champs de mot de passe ont la même valeur en utilisant le formulaire réactif angular2. J'ai vu beaucoup de réponses sur la même chose ici, Forme angulaire 2 validant pour mot de passe répété , Comparaison des champs dans validator avec angular2 , mais aucune ne semblait fonctionner pour moi.Peut quelqu'un aider s'il vous plaît. "This "est indéfini dans ma fonction de validation :( ..____. Partager mon code,

this.addEditUserForm = this.builder.group({
            firstName: ['', Validators.required],
            lastName: ['', Validators.required],
            title: ['', Validators.required],
            email: ['', Validators.required],
            password: ['', Validators.required],
            confirmPass: ['', [Validators.required, this.validatePasswordConfirmation]]
        });
validatePasswordConfirmation(group: FormGroup): any{
        let valid = true;
        // if (this.addEditUserForm.controls.password != this.addEditUserForm.controls.confirmPass) {
        //     valid = false;
        //     this.addEditUserForm.controls.confirmPass.setErrors({validatePasswordConfirmation: true});
        // }
        return valid;
    }
17
RemyaJ

C'est ce qui a finalement fonctionné pour moi -

this.addEditUserForm = this.builder.group({
            firstName: ['', Validators.required],
            lastName: ['', Validators.required],
            title: ['', Validators.required],
            email: ['', Validators.required],
            password: ['', Validators.required],
            confirmPass: ['', Validators.required]
        },{validator: this.checkIfMatchingPasswords('password', 'confirmPass')});



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

Le mieux serait d’avoir un groupe imbriqué dans le groupe de formulaires, où nous avons un validateur personnalisé vérifiant le groupe de formulaires avec password et confirmPass, ainsi, lorsque l’un des champs est modifié, le validateur est déclenché, comme précédemment, il ne se déclenche que lorsque le champ confirmPass est modifié.

Donc, au lieu de cela, faites quelque chose comme ceci à l'intérieur du groupe de forme externe:

// ...
passwords: this.fb.group({
  password: ['', [...]],
  confirmPass: ['', [...]]
}, {validator: this.checkPasswords}) // add a validator for the whole group
// ...

et alors le validateur pourrait ressembler à ceci:

checkPasswords(group: FormGroup) { // here we have the 'passwords' group
  let pass = group.get('password').value;
  let confirmPass = group.get('confirmPass').value;

  return pass === confirmPass ? null : { notSame: true }     
}

Afficher l'erreur de validation pourrait alors être fait comme ceci:

*ngIf="addEditUserForm.hasError('notSame', 'passwords')"

Bien sûr, vous n'avez pas besoin d'un groupe imbriqué, mais il est préférable de ne pas activer le validateur personnalisé à chaque fois que des modifications sont apportées au formulaire. De cette façon, il est déclenché uniquement lorsque des modifications sont apportées à ce groupe de formulaire interne.

21
AJT_82

J'ai fait une approche différente qui fonctionnera pour tout contrôle. Je définis d'abord les contrôles de base du formulaire:

    this.myForm = this.formBuilder.group({
            name: ['', Validators.required],
            password: ['', Validators.required],
    });

Ensuite, je crée un nouveau contrôle pour confirmer la valeur avec mon validateur personnalisé:

    const confirmPasswordControl = new FormControl('', {
            validator: sameValueAs(this.myForm, 'password')
    });

    this.myForm.addControl('confirmPassword', confirmPasswordControl);

Le code du validateur sameValueAs est le suivant, vous pouvez le définir sur un fichier séparé à utiliser n'importe où

export function sameValueAs(group: FormGroup, controlName: string): ValidatorFn {
    return (control: FormControl) => {
          const myValue = control.value;
          const compareValue = group.controls[controlName].value;

          return (myValue === compareValue) ? null : {valueDifferentFrom:controlName};

    };
}
1
Alexander Baron

Si vous voulez le faire de cette façon, vous devez lier la fonction au contexte actuel "this". Passez sur this.validatePasswordConfirmation.bind(this) mais notez que cette fonction sera transmise au FormControl pour la confirmation et non au FormGroup comme vous l'avez indiqué dans la signature de la fonction. 

1
Amit

Pour ceux qui souhaitent ajouter un validateur personnalisé sans être contraints de passer de la validation du groupe de formulaires, il est possible d'ajouter le validateur après avoir défini le formulaire.

Un avantage de cette approche est que l'erreur est ajoutée au contrôle de formulaire et non au groupe de formulaires. De cette façon, il est plus facile d'afficher l'erreur associée au champ puisque nous pouvons vérifier l'erreur directement sur le contrôle de champ/formulaire lui-même.

Voici comment je l'ai implémenté:

Validateur personnalisé

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

export class MismatchValidator {

  static mismatch(otherInputControl: AbstractControl): ValidatorFn {

    return (inputControl: AbstractControl): { [key: string]: boolean } | null => {
      if (inputControl.value !== undefined
        && inputControl.value.trim() != ""
        && inputControl.value !== otherInputControl.value) {
        return { 'mismatch': true };
      }

      return null;
    };
  }
}

Application du validateur personnalisé au contrôle de formulaire

  ngOnInit() {
    this.initForm();
    // The validators are set after defining the form in order to be able to access the password control and pass it to the custom validator as a parameter
    this.setValidators();
  }

  private initForm() {
    this.myForm = this.formBuilder.group({
      password: new FormControl(''),
      passwordConfirmation: new FormControl('')
    });
  }

  private setValidators() {
    const formValidators = {
      "password": Validators.compose([
        Validators.required,
        //....
      ]),
      "passwordConfirmation": Validators.compose([
        Validators.required,
        MismatchValidator.mismatch(this.myForm.get("password")) 
      ])
    }

    this.passwordRecoveryForm.get("password").setValidators(
      formValidators["password"]
    );
    this.passwordRecoveryForm.get("passwordConfirmation").setValidators(
      formValidators["passwordConfirmation"]
    );
  }

Les validateurs sont définis après la définition du formulaire afin de pouvoir accéder au contrôle de mot de passe et de le transmettre au validateur personnalisé en tant que paramètre.

0
Strider

Si vous ne voulez pas passer par un validateur personnalisé, vous pouvez simplement créer un champ de saisie autonome et donc ne pas calculer dans votre formGroup mais plutôt via ngModel

<input type="password" matInput [(ngModel)]="passwordConfirm" [ngModelOptions]="{standalone: true}">

Ensuite, dans vos ts, vous pouvez simplement valider et renvoyer une erreur ou invalider le formulaire si vous le souhaitez. Je viens de le trouver un peu plus rapide et pratique:

// Vérifier la correspondance des mots de passe

  if (this.staffAccountForm.value.password !== this.passwordConfirm) {
    this.snackbar.snackBarSimple('Passwords do not match.');
    return false;
  }
0
Demian S