J'essaie d'implémenter un validateur personnalisé pour vérifier si le mot de passe et le mot de passe de confirmation sont égaux. Le problème est que le validateur obtient un mot de passe indéfini et les paramètres confirmésPassword. Comment puis-je faire ce travail. La fonction fonctionne car si je change la condition === au lieu de! ==, l'erreur est renvoyée correctement lorsque les champs sont identiques Est-ce que quelqu'un sait quelle est l'erreur ici?
signup.component.html
<div class="col-md-7 col-md-offset-1 col-sm-7">
<div class="block">
<div class="well">
<form (onSubmit)="onSubmit()" [formGroup]="signUpForm">
<div class="form-group">
<label for="username" class="control-label">Nombre de usuario:</label>
<input type="text" class="form-control" formControlName="username" title="Please enter your username" placeholder="username">
<p class="help-block" *ngIf="signUpForm.get('username').hasError('required') && signUpForm.get('username').touched">El nombre de usuario es obligatorio</p>
<p class="help-block" *ngIf="signUpForm.get('username').hasError('minlength') && signUpForm.get('username').touched">El nombre de usuario debe tener al menos 6 caracteres</p>
<p class="help-block" *ngIf="signUpForm.get('username').hasError('maxlength') && signUpForm.get('username').touched">El nombre de usuario debe tener menos de 15 caracteres</p>
</div>
<div class="form-group">
<label for="email" class="control-label">E-mail:</label>
<input class="form-control" formControlName="email" title="Please enter your email" placeholder="[email protected]">
<p class="help-block" *ngIf="signUpForm.get('email').hasError('required') && signUpForm.get('email').touched">La dirección de email es obligatoria</p>
<p class="help-block" *ngIf="signUpForm.get('email').hasError('email') && signUpForm.get('email').touched">Debe ingresar una dirección de correo válida</p>
</div>
<div class="form-group">
<label for="password" class="control-label">Contraseña:</label>
<input type="password" class="form-control" formControlName="password" title="Please enter your password" [(ngModel)]="password">
<p class="help-block" *ngIf="signUpForm.get('password').hasError('required') && signUpForm.get('password').touched">Debe ingresar una contraseña</p>
</div>
<div class="form-group">
<label for="confirmedPassword" class="control-label">Confirmar Contraseña:</label>
<input type="password" class="form-control" formControlName="confirmedPassword" title="Please re-enter your password" [(ngModel)]="confirmedPassword">
<p class="help-block" *ngIf="signUpForm.get('confirmedPassword').hasError('required') && signUpForm.get('confirmedPassword').touched">La confirmación de contraseña no puede estar vacía</p>
<p class="help-block" *ngIf="signUpForm.get('confirmedPassword').hasError('passwordMismatch') && signUpForm.get('confirmedPassword').touched">Las contraseñas no coinciden</p>
</div>
<button type="submit" class="btn btn-success" [disabled]="!signUpForm.valid">Registrarse</button>
<a routerLink="/signin" class="btn btn-default" style="">Ya tenes usuario? Logueate</a> {{ creationMessage }}
</form>
</div>
</div>
</div>
signup.component.ts
import { Component, OnInit, ViewChild, Input } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { CustomValidators } from '../../shared/custom-validators';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'app-signup',
templateUrl: './signup.component.html',
styleUrls: ['./signup.component.sass']
})
export class SignupComponent implements OnInit {
signUpForm: FormGroup;
user = {
username: '',
email: '',
password: ''
};
submitted = false;
@Input() password='';
@Input() confirmedPassword='';
constructor() { }
ngOnInit() {
this.signUpForm = new FormGroup({
'username': new FormControl(null, [Validators.required, Validators.minLength(6), Validators.maxLength(15)]),
'email': new FormControl(null, [Validators.required, Validators.email, Validators.minLength(5)]),
'password': new FormControl(null, [Validators.required]),
'confirmedPassword': new FormControl(null, [Validators.required, CustomValidators.passwordsMatch(this.password,this.confirmedPassword).bind(this)])
});
}
onSubmit() {
if (this.signUpForm.valid) {
console.log(this.signUpForm.value);
}
}
}
custom-validators.ts
import { FormControl } from '@angular/forms';
export class CustomValidators{
public static passwordsMatch(password: string, confirmedPassword: string) {
return (control: FormControl) : { [s: string]: boolean } =>{
//getting undefined values for both variables
console.log(password,confirmedPassword);
//if I change this condition to === it throws the error if the
// two fields are the same, so this part works
if (password !== confirmedPassword) {
return { 'passwordMismatch': true }
} else {
//it always gets here no matter what
return null;
}
}
}
}
importer {AbstractControl, FormBuilder, FormGroup, Validators} de
définissez votre mot de passe dans le groupe et inutile d'utiliser "ngModel".
<div class="form-group row" formGroupName="passwords">
<div class="form-group">
<label for="password" class="control-label">Contraseña:</label>
<input type="password" class="form-control" formControlName="password" title="Please enter your password">
<p class="help-block" *ngIf="signUpForm.get('password').hasError('required') && signUpForm.get('password').touched">Debe ingresar una contraseña</p>
</div>
<div class="form-group">
<label for="confirmedPassword" class="control-label">Confirmar Contraseña:</label>
<input type="password" class="form-control" formControlName="confirmedPassword" title="Please re-enter your password">
<p class="help-block" *ngIf="signUpForm.get('confirmedPassword').hasError('required') && signUpForm.get('confirmedPassword').touched">La confirmación de contraseña no puede estar vacía</p>
<p class="help-block" *ngIf="signUpForm.get('confirmedPassword').hasError('passwordMismatch') && signUpForm.get('confirmedPassword').touched">Las contraseñas no coinciden</p>
</div>
buildForm(): void {
this.userForm = this.formBuilder.group({
passwords: this.formBuilder.group({
password: ['', [Validators.required]],
confirm_password: ['', [Validators.required]],
}, {validator: this.passwordConfirming}),
});
}
ajouter cette fonction personnalisée pour valider le mot de passe et confirmer le mot de passe
passwordConfirming(c: AbstractControl): { invalid: boolean } {
if (c.get('password').value !== c.get('confirm_password').value) {
return {invalid: true};
}
}
Erreur d'affichage lorsque le mot de passe ne correspond pas
<div style='color:#ff7355' *ngIf="userForm.get(['passwords','password']).value != userForm.get(['passwords','confirm_password']).value && userForm.get(['passwords','confirm_password']).value != null">
Password does not match</div>
Le problème est que vous êtes mélange du module de formulaires réactifs avec l'approche de saisie}. Cela vous amène à obtenir undefined
lorsque vous transmettez les valeurs au validateur.
Vous n'avez pas besoin de vous lier au ng-model
lorsque vous utilisez les formulaires réactifs. Au lieu de cela, vous devez accéder à la valeur des champs à partir de l'instance de FormGroup
.
Je fais quelque chose comme ça dans une application pour valider la correspondance des mots de passe.
public Credentials: FormGroup;
ngOnInit() {
this.Credentials = new FormGroup({});
this.Credentials.addControl('Password', new FormControl('', [Validators.required]));
this.Credentials.addControl('Confirmation', new FormControl(
'', [Validators.compose(
[Validators.required, this.validateAreEqual.bind(this)]
)]
));
}
private validateAreEqual(fieldControl: FormControl) {
return fieldControl.value === this.Credentials.get("Password").value ? null : {
NotEqual: true
};
}
Notez que le validateur attend un champ FormControl
en tant que paramètre et compare la valeur du champ à celle de la valeur du champ Password
de la Credentials
FormGroup
.
Dans la HTML
, veillez à supprimer le ng-model
.
<input type="password" class="form-control" formControlName="confirmedPassword" title="Please re-enter your password" >
<!-- AND -->
<input type="password" class="form-control" formControlName="password" title="Please enter your password">
J'espère que cela t'aides!
Veuillez mettre à jour le code de FormGroup comme ci-dessous dans Angular5
this.signUpForm = new FormGroup({
'username': new FormControl(null, [Validators.required, Validators.minLength(6), Validators.maxLength(15)]),
'email': new FormControl(null, [Validators.required, Validators.email, Validators.minLength(5)]),
'password': new FormControl(null, [Validators.required]),
'confirmedPassword': new FormControl(null, [Validators.required])
}, this.pwdMatchValidator);
Ajouter la fonction pwdMatchValidator
dans votre composant
pwdMatchValidator(frm: FormGroup) {
return frm.get('password').value === frm.get('confirmedPassword').value
? null : {'mismatch': true};
}
Ajouter un message de validation dans votre modèle
<span *ngIf="confirmedPassword.errors || signUpForm .errors?.mismatch">
Password doesn't match
</span>
Veuillez trouver le composant de travail de matériau angulaire ci-dessous.
Composant Templete Code password.component.html
<form class="cahnge-pwd-form" (ngSubmit)="onSubmit()" name="passwordForm" [formGroup]="passwordForm" #formDir="ngForm">
<div fxLayout='column'>
<mat-form-field>
<input matInput name="password" placeholder="Password" [type]="hide ? 'text' : 'password'" formControlName="password" required>
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
<mat-error *ngIf="password.invalid && (password.dirty || password.touched || isSubmit)">
<span *ngIf="password.errors.required">
Please enter a Password.
</span>
<span *ngIf="password.errors.maxlength">
Please enter a Email no more than 16 characters.
</span>
<span *ngIf="password.errors.minlength">
Please enter a password at least 6 characters.
</span>
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput name="password" placeholder="Confirm Password" [type]="confirm_hide ? 'text' : 'password'" formControlName="confirm_password"
required>
<mat-icon matSuffix (click)="confirm_hide = !confirm_hide">{{confirm_hide ? 'visibility_off' : 'visibility'}}</mat-icon>
<mat-error *ngIf="(confirm_password.invalid && (confirm_password.dirty || confirm_password.touched || isSubmit) || passwordForm.errors?.mismatch)">
<span *ngIf="confirm_password.errors || passwordForm.errors?.mismatch">
Password doesn't match
</span>
</mat-error>
</mat-form-field>
<div fxLayout='row' fxLayoutGap="10px">
<button type="submit" mat-raised-button color="primary">Submit</button>
<button type="button" (click)="formDir.resetForm(passwordForm)" mat-raised-button color="warn">Cancel</button>
</div>
</div>
</form>
Code du composant: password.component.ts
import { Component, OnInit, AfterViewInit } from '@angular/core';
import { FormControl, FormGroup, Validators, FormBuilder } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { PasswordService } from './password.service';
import { PasswordValidation } from './confirm';
@Component({
selector: 'app-password',
templateUrl: './password.component.html',
styleUrls: ['./password.component.css']
})
export class PasswordComponent implements OnInit {
passwordForm: FormGroup;
isSubmit: boolean;
constructor(private router: Router, private passwordService: PasswordService, private toastrService: ToastrService, private route: ActivatedRoute) { }
ngOnInit() {
this.passwordForm = new FormGroup({
'password': new FormControl('', [
Validators.required,
Validators.minLength(6),
Validators.maxLength(16),
]),
'confirm_password': new FormControl('', [
Validators.required,
Validators.minLength(6),
Validators.maxLength(16),
]),
}, this.pwdMatchValidator);
}
pwdMatchValidator(frm: FormGroup) {
return frm.get('password').value === frm.get('confirm_password').value
? null : {'mismatch': true};
}
get password() { return this.passwordForm.get('password'); }
get confirm_password() { return this.passwordForm.get('confirm_password'); }
onSubmit(formvalue):boolean {
this.isSubmit = true;
if (this.passwordForm.invalid) {
return false;
} else {
this.passwordService.updatePassword(this.passwordForm.value)
.subscribe((res) => {
if (res.status == 'success') {
this.toastrService.success(res.msg);
this.router.navigate(['/change-password']);
}
})
return true;
}
}
}
Il existe deux types de validateurs: validateur de groupe de formulaires et validateur de FormControl. Pour vérifier la correspondance de deux mots de passe, vous devez ajouter un validateur FormGroup. Voici mon exemple:
Note: this.fb est le FormBuilder injecté
this.newAccountForm = this.fb.group(
{
newPassword: ['', [Validators.required, Validators.minLength(6)]],
repeatNewPassword: ['', [Validators.required, Validators.minLength(6)]],
},
{validator: this.passwordMatchValidator}
);
passwordMatchValidator(frm: FormGroup) {
return frm.controls['newPassword'].value === frm.controls['repeatNewPassword'].value ? null : {'mismatch': true};
}
et dans le modèle:
<div class="invalid-feedback" *ngIf="newAccountForm.errors?.mismatch && (newAccountForm.controls['repeatNewPassword'].dirty || newAccountForm.controls['repeatNewPassword'].touched)">
Passwords don't match.
</div>
Le point clé consiste ici à ajouter le validateur FormGroup en tant que second paramètre à la méthode group.
Lorsque vous créez le validateur, vous transmettez les valeurs password
et confirmedPassword
, mais les modifications apportées à ces valeurs ne seront pas reflétées dans le validateur.
Les deux options que je vois sont:
FormGroup
et recherchez les valeurs des deux contrôles que vous souhaitez comparer; outhis
, utilisez this.password
et this.confirmedPassword
dans votre validateur.Je referais la même chose que Shailesh Ladumor mais en ajoutant la ligne suivante avant de revenir à la fonction de validation:
c.get('confirm_password').setErrors({'noMatch': true});
Pour que la fonction de validation ressemble à ceci:
passwordConfirming(c: AbstractControl): { invalid: boolean } {
if (c.get('password').value !== c.get('confirm_password').value) {
c.get('confirm_password').setErrors({'noMatch': true});
return {invalid: true};
}
}
Cela définira non seulement le trou userForm
en tant que groupe de formulaire non valide, mais également confirm_password
en tant que contrôle de formulaire non valide.
Avec cela, vous pouvez appeler ultérieurement la fonction suivante dans votre modèle:
public getPasswordConfirmationErrorMessage() {
if (this.userForm.get('confirm_password').hasError('required')) {
return 'You must retype your password';
} else if (this.userForm.get('confirm_password').hasError('noMatch')) {
return 'Passwords do not match';
} else {
return '';
}
}