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
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.
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
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!
* 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>
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
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.
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**
}
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:
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.