Angular 2 formulario de validación para repetir la contraseña

Consulte esta pregunta sobre Comparación de campos en el validador con angular2 . Desafortunadamente, Angular 2 cambió un poco, por lo que la solución parece no funcionar más. Aquí está mi código:

import {IonicApp,Page,NavController,NavParams} from 'ionic/ionic' import {Component} from 'angular2/core' import {FORM_PROVIDERS, FormBuilder, Validators} from 'angular2/common' import {ControlMessages} from '../../components/control-messages' import {ValidationService} from '../../services/validation-service' @Page({ templateUrl: 'build/pages/account/register.html', directives: [ControlMessages] }) export class RegisterPage { constructor(nav:NavController,private builder: FormBuilder) { this.nav = nav this.registerForm = this.builder.group({ 'name' : ['', Validators.required], 'email' : ['',Validators.compose([Validators.required, ValidationService.emailValidator])], 'password' : ['',Validators.required], 'repeat' : ['',this.customValidator] } ) } register() { alert(this.registerForm.value.password) } private customValidator(control) { //console.log(this.registerForm.value.password) //return {isEqual: control.value === this.registerForm.value.password} return true } } 

Mi html:

   
Name Email Password Confirm Password

Pero desafortunadamente, no puedo acceder al valor de “contraseña” en mi función de validación. Si elimino el comentario de console.log (this.registerForm.value.password) , aparece el siguiente mensaje de error:

EXCEPCIÓN: TypeError: no se puede leer la propiedad ‘valor’ de indefinido

¿Alguna idea? Gracias.

Veo varios problemas en tu código. Intenta utilizar la palabra clave this en la función del validador y esto no corresponde a la instancia del componente. Es porque hace referencia a la función cuando la configura como una función de validación.

Además, el valor asociado con un control se puede alcanzar en la propiedad del value .

Dicho esto, creo que la forma correcta de validar sus dos campos juntos es crear un grupo y asociar un validador en él:

 import { FormBuilder, Validators } from '@angular/forms'; ... constructor(private fb: FormBuilder) { // <--- inject FormBuilder this.createForm(); } createForm() { this.registerForm = this.fb.group({ 'name' : ['', Validators.required], 'email': ['', [Validators.required, Validators.email] ], 'passwords': this.fb.group({ password: ['', Validators.required], repeat: ['', Validators.required] }, {validator: this.matchValidator}) }); } 

De esta forma, tendrá acceso a todos los controles del grupo y no solo a uno, y ya no necesitará usar la palabra clave this ... Se puede acceder a los controls de formulario del grupo usando la propiedad de controls de FormGroup. FormGroup se proporciona cuando se activa la validación. Por ejemplo:

 matchValidator(group: FormGroup) { var valid = false; for (name in group.controls) { var val = group.controls[name].value (...) } if (valid) { return null; } return { mismatch: true }; } 

Vea este informe para más detalles:

  • Validación de campo cruzado en Angular2

Editar

Para mostrar el error, simplemente puede usar lo siguiente:

  
The two passwords aren't the same

Implementé un validador de coincidencias de contraseñas personalizado para Angular 4.

Además de verificar si coinciden dos valores, también se suscribe a cambios de otro control y vuelve a validar cuando se actualiza cualquiera de los dos controles. Siéntase libre de usarlo como referencia para su propia implementación o simplemente cópielo directamente.

Aquí está el enlace a la solución: https://gist.github.com/slavafomin/17ded0e723a7d3216fb3d8bf845c2f30 .


Y aquí estoy proporcionando una copia del código:

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

Uso

Así es como puedes usarlo con formas reactivas:

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

Se pueden encontrar validadores más actualizados aquí: moebius-mlm / ng-validators .

encontró una solución mucho más simple. No estoy seguro de si esta es la manera correcta de hacerlo, pero funciona para mí

          

Ver

 pattern="{{registerCredentials.password}}" 

Solución angular 4.3.3!

Puede hacerlo usando: [formGroup] , formGroupName , formControlName en html y new FormGroup , new FormControl y método personalizado de areEqual en TS

reg.component.html

 
PASSWORDS do not match

reg.component.ts

 export class HomeHeaderSettingsModalComponent implements OnInit { userFormPassword: FormGroup; // ... static areEqual(c: AbstractControl): ValidationErrors | null { const keys: string[] = Object.keys(c.value); for (const i in keys) { if (i !== '0' && c.value[ keys[ +i - 1 ] ] !== c.value[ keys[ i ] ]) { return { areEqual: true }; } } } ngOnInit() { this.userFormPassword = new FormGroup({ 'current_password': new FormControl(this.user.current_password, [ Validators.required, ]), 'passwords': new FormGroup({ 'new_password': new FormControl(this.user.new_password, [ Validators.required ]), 'repeat_new_password': new FormControl(this.user.repeat_new_password, [ Validators.required ]) }, HomeHeaderSettingsModalComponent.areEqual) }); } } 

Resultado: resultado

Si está utilizando RC.5 y no puede encontrar ControlGroup, puede intentar usar FormGroup. Puede obtener más información de mi respuesta:

Angular 2 RC.5 formulario de validación para la repetición de contraseña

Al usar esta biblioteca ng2-validation-manager , puede hacer esto fácilmente:

 this.form = new ValidationManager({ 'password' : 'required|rangeLength:8,50', 'repassword' : 'required|equalTo:password' }); 

Además, a partir del angular 2 rc4 con formularios 0.2.0, el marcado y el atributo que llama al nombre del grupo utilizado para abarcar las entradas agrupadas es necesario para evitar errores.

 
group input fields here...

Guarde la contraseña en la variable de instancia.

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

Luego úsala en tu grupo de formularios.

  this.registrationForm = this.fb.group({ 'email': ['', [ Validators.required, NGValidators.isEmail, ] ], 'password': this.password, 'password2': ['', [Validators.required, this.passwordMatch]] }); 

Entonces la función se ve así.

  private passwordMatch() { let that = this; return (c: FormControl) => { return (c.value == that.password.value) ? null : {'passwordMatch': {valid: false}}; } } 

Sé que no es la mejor solución, ¡pero funciona!

Bueno, busqué una respuesta sobre este tema y todos eran demasiado grandes para mi pereza, así que lo hice así. Creo que hace bien el trabajo.

Utilicé el ngModel para vincular la contraseña y repetir la entrada de contraseña y luego he mostrado u ocultado el mensaje de comparación div con contraseña con el atributo [oculto] en angular 2.

      
Passwords do not match!

Encontré una solución que me hizo más feliz en cuanto a la coherencia del código y el manejo de errores:

Primero: cree una clase de validación personalizada con un método estático que haga la validación

Este método debe tener un parámetro AbstractControl que inyecta angular

Tenga en cuenta que pasará esto en el control ConfirmPassword, por lo que debe llamar al padre para llegar al FormGroup. Desde allí, llama a formGroup.get (‘myControl’) y obtén los controles para la contraseña y confirma como los llamaste cuando creaste el grupo de formularios.

 import {AbstractControl} from '@angular/forms'; export class PasswordValidation { static MatchPassword(AC: AbstractControl) { const formGroup = AC.parent; if (formGroup) { const passwordControl = formGroup.get('Password'); // to get value in input tag const confirmPasswordControl = formGroup.get('Confirm'); // to get value in input tag if (passwordControl && confirmPasswordControl) { const password = passwordControl.value; const confirmPassword = confirmPasswordControl.value; if (password !== confirmPassword) { return { matchPassword: true }; } else { return null; } } } return null; } } 

2º: Use su Validador de clientes al igual que usa angulares

 this.registerForm = this.fb.group({ // <-- the parent FormGroup Email: ['', Validators.required ], Username: ['', Validators.required ], FirstName: ['', Validators.required ], Password: ['', [ Validators.required, Validators.minLength(6) ] ], Confirm: ['', [ Validators.required, PasswordValidation.MatchPassword ] ] }); 

Angular agregará entonces la 'contraseña de coincidencia': verdadera para sus errores de control de confirmación exactamente como agregaría verdadera 'requerida' cuando falta un valor

Resumen

  • Activa la validación cada vez que cambia el valor del otro control.
  • Darse de baja para evitar memory leaks
  • devolver {match: true} nos permitirá verificar si un control dado tiene el error usando myControl.hasError('match')

Implementación

 import { AbstractControl, ValidatorFn } from '@angular/forms'; import { Subscription } from 'rxjs/Subscription'; export function matchOtherValidator(otherControlName: string): ValidatorFn { return (control: AbstractControl): { [key: string]: any } => { const otherControl: AbstractControl = control.root.get(otherControlName); if (otherControl) { const subscription: Subscription = otherControl .valueChanges .subscribe(() => { control.updateValueAndValidity(); subscription.unsubscribe(); }); } return (otherControl && control.value !== otherControl.value) ? {match: true} : null; }; } 

Ejemplo

 this.registerForm = formBuilder.group({ email: ['', [ Validators.required, Validators.email ]], password: ['', [ Validators.required, Validators.minLength(8) ]], confirmPassword: ['', [ Validators.required, matchOtherValidator('password') ]] }); 

Mi solución para Angular 4.3.4, que no requiere FormGroup adicional:

  • Registre un validador personalizado para la verificación de contraseñas repeatedPassword si las contraseñas son las mismas
  • suscriba el controlador en password.valueChanges durante la creación del formulario, y llame .updateValueAndValidity() method en .updateValueAndValidity() method

Aquí hay un código:

 form: FormGroup passwordFieldName = 'password' repeatedPasswordFieldName = 'repeatedPassword' createForm() { this.form = this.formBuilder.group({ login: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(255), Validators.email]], [passwordFieldName]: ['', [Validators.required, Validators.minLength(6), Validators.maxLength(255)]], [repeatedPasswordFieldName]: ['', [Validators.required, this.samePassword]] }); this.form .get(passwordFieldName) .valueChanges.subscribe(() => { this.form .get(repeatedPasswordFieldName).updateValueAndValidity(); }) } samePassword(control: FormControl) { if (!control || !control.parent) { return null; } if (control.value !== control.parent.get(passwordFieldName).value) { return {'passwordMismatch': true} } return null; } 

Solo quiero publicar mi solución:

 this.authorizationSettings = formBuilder.group({ currentPassword: [null, Validators.compose([Validators.required, Validators.minLength(8)])], newPassword: [null, Validators.compose([Validators.required, Validators.minLength(8)])], repeatNewPassword: [null] }); this.authorizationSettings.controls.newPassword.valueChanges.subscribe(data => { if (data) { data = data.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); } this.authorizationSettings.controls.repeatNewPassword .clearValidators(); this.authorizationSettings.controls.repeatNewPassword .setValidators(Validators.compose([Validators.required, Validators.pattern(data)])); }); 

Necesitamos crear un grupo de formularios primero, luego suscribirnos al primer campo de contraseña nuevo y luego agregar la validación al campo de repetición.

Esta es mi manera de usar Validadores Angulares

COMPONENTE:

 import { UserModel } from '../../settings/users/user.model'; import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormRequestModel } from '../Shared/form.model'; import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-add-user', templateUrl: './add-user.component.html', styleUrls: ['./add-user.component.scss'] }) export class AddUserComponent implements OnInit { passwordsForm: FormGroup; user: UserModel; constructor(private fb: FormBuilder) { } ngOnInit() { this.passwordsForm = this.fb.group({ inputPassword: ['', Validators.compose([Validators.required, Validators.minLength(6), Validators.maxLength(50)])], inputPasswordAgain: [''] }); } } 

HTML:

  

Password must contain at least 6 characters!!

Both passwords must be equal!

Si desea crear una directiva y usarla, vea esto

Aquí está el código de directiva completo

 import { Directive, Attribute } from '@angular/core'; import { Validator, NG_VALIDATORS } from '@angular/forms'; @Directive({ selector: '[advs-compare]', providers: [{provide: NG_VALIDATORS, useExisting: CompareDirective, multi: true}] }) export class CompareDirective implements Validator { constructor(@Attribute('advs-compare') public comparer: string){} validate(c: Control): {[key: string]: any} { let e = c.root.get(this.comparer); if(e && c.value !== e.value){ return {"compare": true}; } return null; } } 

Para obtener más información sobre cómo usarlo, consulte http://www.advancesharp.com/blog/1226/angular-5-email-compare-password-validation-different-ways

Solo comenzando con Angular y encontré esta solución, no sé si es una buena práctica para ti:

  // Custom password confirmation validation static matchFieldValidator(fieldToMatch:string) : ValidatorFn { return (control : AbstractControl) : { [key: string]: any;} => { let confirmField = control.root.get(fieldToMatch); return (confirmField && control.value !== confirmField.value) ? {match:false} : null; } } 

De esta forma, puedes hacer algo como esto al configurar las reglas de validación

  this.registrationForm = fb.group({ ... password1 : ['', [Validators.minLength(3)]], // remember to replace RegisterComponent with YOUR class name password2 : ['', [RegisterComponent.matchFieldValidator('password1')]], }); 

Esta es la manera más fácil que sigo. He eliminado el código que no es relevante.

Creo que esto te ayudará.

auth.component.ts, auth.component.html, auth.component.css

 import { Component, OnInit, EventEmitter, Input, Output ,Directive, forwardRef, Attribute,OnChanges, SimpleChanges} from '@angular/core'; import { NG_VALIDATORS,Validator,Validators,AbstractControl,ValidatorFn } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { RegisterUser } from '../shared/models'; @Component({ moduleId: module.id, selector: 'auth-page', styleUrls: ['./auth.component.css'], templateUrl: './auth.component.html' }) export class AuthComponent implements OnInit { userRegisterModel: RegisterUser = new RegisterUser(); constructor(private route: ActivatedRoute, private router: Router) { } ngOnInit() { this.userRegisterModel.LoginSource = 'M';//Manual,Facebook,Google } userRegister() { console.log(this.userRegisterModel); } } 
 .validation { margin:0; padding-top: 1px; padding-bottom: 0px; } .validation .message { font-size: 10px; color: #de1a16; } 
  
 
Name is required
Only alphabets allowed
 
Name is required
Only alphabets allowed
 
Email is required
Email format should be john@doe.com
 
Password should be 6digit
Password is required
 
Passwords did not match

No creo que necesitemos un validador personalizado para contraseñas coincidentes, esto se puede lograr fácilmente mediante el uso de formname.controls['controlName'].value .

  
Enter valid password between 7 and 14 characters.
Password do not match

En fileName.component.ts el control de formulario declarado como:

 'password':[null, Validators.compose([Validators.required, Validators.minLength(7), Validators.maxLength(14))], 'confPassword':[null, Validators.required] 

Respondiendo a la persona de Zhou Hao que planteó la cuestión del debate, creo que esto es lo que estabas buscando porque a mí me pasó lo mismo que a ti, dijo que la variable no estaba definida y la resolvió así:

  static comparePassword(control) { try { control.parent.value.password; if (control.parent.value.password == control.value) { return null; } else { return { 'invalidValue': true }; } } catch (e) { e.message; } }