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:
- defina su validador en
FormGroup
y busque los valores de los dos controles que desea comparar; o -
this.password
ya está vinculado athis
, usethis.password
ythis.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.