web-dev-qa-db-fra.com

Confirmer la validation du mot de passe dans Angular 6

Je souhaite effectuer des validations password et confirm password à l'aide de composants material uniquement, ainsi qu'un message d'erreur sous le champ confirm password si confirm password field doesn't match et if it is empty. .

Essayé cette vidéo aussi.

C'est le composant matériel que je recherche

 enter image description here

HTML

     <mat-form-field >
        <input matInput  placeholder="New password" [type]="hide ? 'password' 
          : 'text'" [formControl]="passFormControl" required>
        <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 
          'visibility_off'}}</mat-icon>
        <mat-error *ngIf="passFormControl.hasError('required')">
            Please enter your newpassword
         </mat-error>
      </mat-form-field>

      <mat-form-field >
         <input matInput  placeholder="Confirm password" [type]="hide ? 
              'password' : 'text'" [formControl]="confirmFormControl" 
                    required>
         <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 
                'visibility_off'}}</mat-icon>
         <mat-error *ngIf="confirmFormControl.hasError('required')">
          Confirm your password
          </mat-error>
      </mat-form-field>

TS

     import {Component, OnInit } from '@angular/core';
     import {FormControl, FormGroupDirective, NgForm, Validators} from 
             '@angular/forms';
     import {ErrorStateMatcher} from '@angular/material/core';

     @Component({
            selector: 'asd-set-pass',
            templateUrl: './set-pass.component.html',
             styleUrls: ['./set-pass.component.css']
         })

       passFormControl = new FormControl('', [
            Validators.required,
        ]);
        confirmFormControl = new FormControl('', [
            Validators.required,
            ]);

             hide =true;

       }

Cela valide bien les conditions suivantes 1) Si les champs mot de passe et confirmation sont vides, le texte d'erreur affiché est vide.

Je veux comparer aux champs dans le fichier (.ts), comme sa validation pour le champ vide, et une erreur à venir si le champ de confirmation du mot de passe est vide.

17
Shankar

Cette question pourrait être résolue par une combinaison des deux réponses suivantes: https://stackoverflow.com/a/43493648/6294072 et https://stackoverflow.com/a/47670892/6294072

Donc, tout d’abord, vous aurez besoin d’un validateur personnalisé pour vérifier les mots de passe, qui pourrait ressembler à ceci:

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

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

et vous créez un groupe de formulaires pour vos champs, au lieu de deux contrôles de formulaire, puis marquez ce validateur personnalisé pour votre groupe de formulaires:

this.myForm = this.fb.group({
  password: ['', [Validators.required]],
  confirmPassword: ['']
}, {validator: this.checkPasswords })

et comme mentionné dans une autre réponse, le mat-error indique uniquement si un FormControl n'est pas valide, vous avez donc besoin d'un indicateur d'état d'erreur:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control && control.invalid && control.parent.dirty);
    const invalidParent = !!(control && control.parent && control.parent.invalid && control.parent.dirty);

    return (invalidCtrl || invalidParent);
  }
}

dans ce qui précède, vous pouvez modifier le moment pour afficher un message d'erreur. Je ne montrerais le message que lorsque le champ password est touché. Aussi, j'aimerais que ci-dessus, supprime le validateur required du champ confirmPassword, car le formulaire n'est de toute façon pas valide si les mots de passe ne correspondent pas.

Puis dans le composant, créez une nouvelle ErrorStateMatcher:

matcher = new MyErrorStateMatcher();

Enfin, le modèle ressemblerait à ceci:

<form [formGroup]="myForm">
  <mat-form-field>
    <input matInput placeholder="New password" formControlName="password" required>
    <mat-error *ngIf="myForm.hasError('required', 'password')">
        Please enter your new password
    </mat-error>
  </mat-form-field>

  <mat-form-field>
    <input matInput placeholder="Confirm password" formControlName="confirmPassword" [errorStateMatcher]="matcher">
    <mat-error *ngIf="myForm.hasError('notSame')">
        Passwords do not match
    </mat-error>  
  </mat-form-field>
</form>

Voici une démo pour vous avec le code ci-dessus: StackBlitz

44
AJT_82

Dans le cas où vous avez plus que des champs Mot de passe et Vérifier le mot de passe . De même, le champ Confirmer le mot de passe ne met en évidence qu'une erreur lorsque l'utilisateur écrit quelque chose dans ce champ:

validators.ts

import { FormGroup, FormControl, Validators, FormBuilder, FormGroupDirective, NgForm } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';

export const EmailValidation = [Validators.required, Validators.email];
export const PasswordValidation = [
  Validators.required,
  Validators.minLength(6),
  Validators.maxLength(24),
];

export class RepeatPasswordEStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return (control && control.parent.get('password').value !== control.parent.get('passwordAgain').value && control.dirty)
  }
}
export function RepeatPasswordValidator(group: FormGroup) {
  let password = group.controls.password.value;
  let passwordConfirmation = group.controls.passwordAgain.value;

  return password === passConfirmation ? null : { passwordsNotEqual: true }     
}

register.component.ts

import { FormGroup, FormControl, Validators, FormBuilder} from '@angular/forms';
import { EmailValidation, PasswordValidation, RepeatPasswordEStateMatcher, RepeatPasswordValidator } from 'validators';

...

form: any;
passwordsMatcher = new RepeatPasswordEStateMatcher;


constructor(private formBuilder: FormBuilder) {
    this.form = this.formBuilder.group ( {
      email: new FormControl('', EmailValidation),
      password: new FormControl('', PasswordValidation),
      passwordAgain: new FormControl(''),
      acceptTerms: new FormControl('', [Validators.requiredTrue])
    }, { validator: RepeatPasswordValidator });
  }

...

register.component.html

<form [formGroup]="form" (ngSubmit)="submitAccount(form)">
    <div class="form-content">
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="email" placeholder="Email">
            <mat-error *ngIf="form.get('email').hasError('required')">
                E-mail is mandatory.
            </mat-error>
            <mat-error *ngIf="form.get('email').hasError('email')">
                Incorrect E-mail.
            </mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="password" placeholder="Password" type="password">
            <mat-hint class="ac-form-field-description">Between 6 and 24 characters.</mat-hint>
            <mat-error *ngIf="form.get('password').hasError('required')">
                Password is mandatory.
            </mat-error>
            <mat-error *ngIf="form.get('password').hasError('minlength')">
                Password with less than 6 characters.
            </mat-error>
            <mat-error *ngIf="form.get('password').hasError('maxlength')">
                Password with more than 24 characters.
            </mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-form-field>
            <input matInput formControlName="passwordAgain" placeholder="Confirm the password" type="password" [errorStateMatcher]="passwordsMatcher">
            <mat-error *ngIf="form.hasError('passwordsNotEqual')" >Passwords are different. They should be equal!</mat-error>
            </mat-form-field>
        </div>
        <div class="form-field">
            <mat-checkbox name="acceptTerms" formControlName="acceptTerms">I accept terms and conditions</mat-checkbox>
        </div>
    </div>
    <div class="form-bottom">
        <button mat-raised-button [disabled]="!form.valid">Create Account</button>
    </div>
</form>

j'espère que ça aide!

3
Celso Soares

* Cette solution est pour forme réactive

Vous avez peut-être entendu dire que le mot de passe de confirmation est connu sous le nom de validation inter-champs. Alors que le validateur de niveau de champ que nous écrivons habituellement ne peut être appliqué qu’à un seul champ. Pour la validation par recoupement, vous devez probablement écrire un validateur de niveau parent. Pour plus particulièrement le cas de la confirmation du mot de passe, je préférerais faire:

this.form.valueChanges.subscribe(field => {
  if (field.password !== field.confirm) {
    this.confirm.setErrors({ mismatch: true });
  } else {
    this.confirm.setErrors(null);
  }
});

Et voici le modèle:

<mat-form-field>
      <input matInput type="password" placeholder="Password" formControlName="password">
      <mat-error *ngIf="password.hasError('required')">Required</mat-error>
</mat-form-field>
<mat-form-field>
    <input matInput type="password" placeholder="Confirm New Password" formControlName="confirm">`enter code here`
    <mat-error *ngIf="confirm.hasError('mismatch')">Password does not match the confirm password</mat-error>
</mat-form-field>
1
goldenbearkin

J'utilise angular 6 et j'ai cherché le meilleur moyen de faire correspondre le mot de passe et de le confirmer. Ceci peut également être utilisé pour faire correspondre deux entrées quelconques dans un formulaire. J'ai utilisé des directives angulaires. J'ai eu envie de les utiliser 

ng g d compare-validators --spec false et je serai ajouté dans votre module. Ci-dessous la directive

import { Directive, Input } from '@angular/core';
import { Validator, NG_VALIDATORS, AbstractControl, ValidationErrors } from '@angular/forms';
import { Subscription } from 'rxjs';

@Directive({
  // tslint:disable-next-line:directive-selector
  selector: '[compare]',
  providers: [{ provide: NG_VALIDATORS, useExisting: CompareValidatorDirective, multi: true}]
})
export class CompareValidatorDirective implements Validator {
  // tslint:disable-next-line:no-input-rename
  @Input('compare') controlNameToCompare;

  validate(c: AbstractControl): ValidationErrors | null {
    if (c.value.length < 6 || c.value === null) {
      return null;
    }
    const controlToCompare = c.root.get(this.controlNameToCompare);

    if (controlToCompare) {
      const subscription: Subscription = controlToCompare.valueChanges.subscribe(() => {
        c.updateValueAndValidity();
        subscription.unsubscribe();
      });
    }

    return controlToCompare && controlToCompare.value !== c.value ? {'compare': true } : null;
  }

}

Maintenant dans votre composant

<div class="col-md-6">
              <div class="form-group">
                <label class="bmd-label-floating">Password</label>
                <input type="password" class="form-control" formControlName="usrpass" [ngClass]="{ 'is-invalid': submitAttempt && f.usrpass.errors }">
                <div *ngIf="submitAttempt && signupForm.controls['usrpass'].errors" class="invalid-feedback">
                  <div *ngIf="signupForm.controls['usrpass'].errors.required">Your password is required</div>
                  <div *ngIf="signupForm.controls['usrpass'].errors.minlength">Password must be at least 6 characters</div>
                </div>
              </div>
            </div>
            <div class="col-md-6">
              <div class="form-group">
                <label class="bmd-label-floating">Confirm Password</label>
                <input type="password" class="form-control" formControlName="confirmpass" compare = "usrpass"
                [ngClass]="{ 'is-invalid': submitAttempt && f.confirmpass.errors }">
                <div *ngIf="submitAttempt && signupForm.controls['confirmpass'].errors" class="invalid-feedback">
                  <div *ngIf="signupForm.controls['confirmpass'].errors.required">Your confirm password is required</div>
                  <div *ngIf="signupForm.controls['confirmpass'].errors.minlength">Password must be at least 6 characters</div>
                  <div *ngIf="signupForm.controls['confirmpass'].errors['compare']">Confirm password and Password dont match</div>
                </div>
              </div>
            </div>

J'espère que ça aide

1
Niclausel

Je suggère d'utiliser la bibliothèque ng-form-rules . C'est une bibliothèque géniale pour créer différents types de formulaires avec une logique de validation découplée du composant (et réutilisable). Ils ont grande documentation , exemples et une video qui montre un tas de ses fonctionnalités . Faire une telle validation (vérifier l’égalité de deux contrôles de formulaire) est trivial.

Vous pouvez consulter leur README pour obtenir des informations de haut niveau et un exemple élémentaire.

0
Chris Knight

Ma réponse est très simple> J'ai créé un mot de passe et confirme la validation du mot de passe en utilisant un modèle dérivé de angular 6

Mon fichier html

<div class="form-group">
  <label class="label-sm">Confirm Password</label>
  <input class="form-control" placeholder="Enter Password" type="password" #confirm_password="ngModel" [(ngModel)]="userModel.confirm_password" name="confirm_password" required (keyup)="checkPassword($event)" />
  <div *ngIf="confirm_password.errors && (confirm_password.dirty||confirm_password.touched||signup.submitted)">
  <div class="error" *ngIf="confirm_password.errors.required">Please confirm your password</div>
  </div>
  <div *ngIf="i" class='error'>Password does not match</div>
</div>

Mon fichier TypeScript

      public i: boolean;

      checkPassword(event) {
        const password = this.userModel.password;
        const confirm_new_password = event.target.value;

        if (password !== undefined) {
          if (confirm_new_password !== password) {
            this.i = true;
          } else {
            this.i = false;
          }
        }
      }

en cliquant sur le bouton d'envoi, je vérifie si la valeur de i est vraie ou fausse

si vrai 

if (this.i) {
      return false;
    }

else{
**form submitted code comes here**
}
0
Mukul Kashyap

J'ai trouvé un bug dans la réponse de AJT_82. Comme je n'ai pas assez de réputation pour commenter sous la réponse de AJT_82, je dois publier le bogue et la solution dans cette réponse.

Voici le bug: 

 enter image description here

Solution: dans le code suivant:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control && control.invalid && control.parent.dirty);
    const invalidParent = !!(control && control.parent && control.parent.invalid && control.parent.dirty);

    return (invalidCtrl || invalidParent);
  }
}

Remplacez control.parent.invalid par control.parent.hasError('notSame') pour résoudre ce problème.

Après les petits changements, le problème a été résolu.

 enter image description here

0
Henry