javascript - validate - Validación de campo cruzado en Angular2
custom validator angular 6 (3)
Es necesario asignar un validador personalizado a un grupo de formulario completo para implementar esto. Algo como esto:
this.form = this.fb.group({
name: ['''', Validators.required],
email: ['''', Validators.required]
matchingPasswords: this.fb.group({
password: ['''', Validators.required],
confirmPassword: ['''', Validators.required]
}, {validator: this.matchValidator}) <--------
});
De esta manera, tendrá acceso a todos los controles del grupo y no solo a uno ... Se puede acceder a este mediante la propiedad de controls
de FormGroup. El 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 esta pregunta para más detalles:
Estoy construyendo una aplicación del lado del cliente Angular2. Actualmente estoy trabajando en los componentes de membresía e integrando los componentes del lado del cliente con MVC6 vNext Identity v3. He escrito validadores de contraseña Angular2 personalizados de la siguiente manera:
needsCapitalLetter(ctrl: Control): {[s: string]: boolean} {
if(!ctrl.value.match(/[A-Z]/))
return {''needsCapitalLetter'': true}
return null;
}
needsLowerLetter(ctrl: Control): {[s: string]: boolean} {
if(!ctrl.value.match(/[a-z]/))
return {''needsLowerLetter'': true}
return null;
}
needsNumber(ctrl: Control): {[s: string]: boolean} {
if(!ctrl.value.match(//d/))
return {''needsNumber'': true}
return null;
}
needsSpecialCharacter(ctrl: Control): {[s: string]: boolean} {
if(!ctrl.value.match(/[^a-zA-Z/d]/))
return {''needsSpecialCharacter'': true}
return null;
}
Esto funciona muy bien, y me encanta Angular2, pero ahora estoy tratando de escribir un validador que verifique que la "Confirmar contraseña" sea igual a la "Contraseña". Para hacer esto, necesito poder validar un campo contra el otro. Puedo hacer esto fácilmente en el nivel de los componentes, y solo revisar el desenfoque, el envío o cualquier otra forma, pero esto evita el sistema de validación Angular2 ngForm. Me gustaría mucho descubrir cómo escribir un Validador Angular2 para un campo que pueda verificar el valor de otro campo, pasando el nombre del otro campo o algo parecido a este. Parece que esto debería ser una capacidad, ya que sería una necesidad en casi cualquier UI de aplicaciones de negocios complejas.
No lo he hecho yo mismo, pero podría crear ControlGroup
con dos campos de contraseña y validarlo. Los controles tienen .valueChanges
propiedad .valueChanges
que es observable y puede combinarlos y verificar la igualdad allí.
Victor Savkin habla brevemente sobre ese caso exacto en Angular Air en este episodio
También puede utilizar un validador de directivas personalizado para comparar los campos.
En tu html:
<div>
<label>Password</label>
<input type="password" name="password" [ngModel]="user.password"
required #password="ngModel">
<small [hidden]="password.valid || (password.pristine && !f.submitted)">
Password is required
</small>
</div>
<div>
<label>Retype password</label>
<input type="password" name="confirmPassword" [ngModel]="user.confirmPassword"
required validateEqual="password" #confirmPassword="ngModel">
<small [hidden]="confirmPassword.valid || (confirmPassword.pristine && !f.submitted)">
Password mismatch
</small>
</div>
Y su directiva:
import { Directive, forwardRef, Attribute } from ''@angular/core'';
import { Validator, AbstractControl, NG_VALIDATORS } from ''@angular/forms'';
@Directive({
selector: ''[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]'',
providers: [
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidator), multi: true }
]
})
export class EqualValidator implements Validator {
constructor( @Attribute(''validateEqual'') public validateEqual: string) {}
validate(c: AbstractControl): { [key: string]: any } {
// self value (e.g. retype password)
let v = c.value;
// control value (e.g. password)
let e = c.root.get(this.validateEqual);
// value not equal
if (e && v !== e.value) return {
validateEqual: false
}
return null;
}
}
Aquí está la solución completa en plunkr: