test online inside javascript angular angular-reactive-forms angular-validation

javascript - online - El validador personalizado en forma reactiva para la contraseña y confirma la coincidencia de la contraseña obteniendo parámetros no definidos en Angular 4



get element inside iframe jquery (7)

Estoy intentando implementar un validador personalizado para verificar si la contraseña y la confirmación de contraseña son iguales. El problema es que el validador está obteniendo una contraseña no definida y parámetros confirmados de contraseña. ¿Cómo hago este trabajo? La función funciona porque si cambio la condición a === en lugar de! == arroja el error correctamente cuando los campos son los mismos. ¿Alguien sabe cual es el error aquí?

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

validadores personalizados.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; } } } }


importar {AbstractControl, FormBuilder, FormGroup, Validators} desde

configure la entrada de su contraseña en el grupo y no necesita usar "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}), }); }

agregue esta función personalizada para validar la contraseña y confirmar la contraseña

passwordConfirming(c: AbstractControl): { invalid: boolean } { if (c.get(''password'').value !== c.get(''confirm_password'').value) { return {invalid: true}; } }

Mostrar error cuando la contraseña no coincide

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


Cuando está creando el validador, pasa los valores de password y password confirmedPassword , pero los cambios en esos valores no se reflejarán en el validador.

Las dos opciones que veo son:

  1. defina su validador en FormGroup y busque los valores de los dos controles que desea comparar; o
  2. this.password ya está vinculado a this , use this.password y this.confirmedPassword en su validador.

El problema es que está mezclando el módulo de formas reactivas con el enfoque de entrada . Esto está causando que se undefined al pasar los valores al validador.

No es necesario vincularse al ng-model cuando se usan las formas reactivas. En su lugar, debe acceder al valor de los campos desde la instancia de FormGroup .

Hago algo como esto en una aplicación para validar la coincidencia de contraseñas.

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

Tenga en cuenta que el validador espera un campo FormControl como parámetro y compara el valor del campo con el valor del campo Password del grupo de Credentials FormGroup .

En el HTML asegúrese de eliminar el 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">

¡Espero que esto ayude!


Haría lo mismo que Shailesh Ladumor pero agregando la siguiente línea antes de regresar en la función de validación:

c.get(''confirm_password'').setErrors({''noMatch'': true});

Para que la función de validación se vea así:

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

Esto no solo establecerá el agujero userForm como un grupo de formulario no válido, sino que también establecerá confirm_password como un control de formulario no válido.

Con esto podrás más tarde llamar la siguiente función en tu plantilla:

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

}


Hay dos tipos de validadores: el validador FormGroup y el validador FormControl . Para verificar que dos contraseñas coinciden, debe agregar un validador de FormGroup. A continuación se muestra mi ejemplo:

Nota: this.fb es el FormBuilder inyectado

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

y en el templo:

<div class="invalid-feedback" *ngIf="newAccountForm.errors?.mismatch && (newAccountForm.controls[''repeatNewPassword''].dirty || newAccountForm.controls[''repeatNewPassword''].touched)"> Passwords don''t match. </div>

El punto clave aquí es agregar el validador de FormGroup como el segundo parámetro al método de grupo.


Por favor actualice el código de FormGroup como abajo en 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);

Agregue la función pwdMatchValidator en su componente

pwdMatchValidator(frm: FormGroup) { return frm.get(''password'').value === frm.get(''confirmedPassword'').value ? null : {''mismatch'': true}; }

Añadir mensaje de validación en su plantilla

<span *ngIf="confirmedPassword.errors || signUpForm .errors?.mismatch"> Password doesn''t match </span>

Por favor encuentre el componente de trabajo del material angular a continuación.

Componente Templete Código 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>

Código del componente: 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; } } }


const form = new FormGroup({ password: new FormControl('''', Validators.minLength(2)), passwordConfirm: new FormControl('''', Validators.minLength(2)), }, passwordMatchValidator); function passwordMatchValidator(g: FormGroup) { return g.get(''password'').value === g.get(''passwordCenter code hereonfirm'').value ? null : {''mismatch'': true}; }

Debe crear un nuevo servicio y puede llamar al servicio creado mientras desea validar la contraseña y los campos de confirmación.