Validación condicional en el método valueChanges en formularios reactivos Angular
¿Sabes cómo utilizar Angular detección de cambios de valor de Reactive Forms? Esta publicación de blog le mostrará los caminos.
En esta publicación de blog, aprenderemos a usar Angular detección de cambios de valor de Reactive Forms y habilitaremos la validación condicional sobre la base de eso con la ayuda de las mejores y más completas bibliotecas de componentes de Angular que existen: Ignite UI.
Aprende a crear tu primer formulario reactivo Angular aquí.
Supongamos que tiene un formulario reactivo creado con la clase FormBuilder como se muestra a continuación:
ngOnInit() {
this.loginForm = this.fb.group({
email: [null, Validators.required],
password: [null, [Validators.required, Validators.maxLength(8)]],
phonenumber: [null]
});
}
Ha creado loginForm, que tiene tres controles: correo electrónico, contraseña y número de teléfono. En este caso, está utilizando FormBuilder para crear un formulario reactivo. En la plantilla de componente, puede adjuntar loginForm como se muestra en la lista de códigos a continuación. Mediante el enlace de propiedades, la propiedad formGroup del elemento de formulario HTML se establece en loginForm y el valor formControlName de estos controles se establece en la propiedad FormControl individual de FormBuilder.
<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
<input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
<div class="alert alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
Email is required
</div>
<input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
<input formControlName='phonenumber' type="text" class="form-control" placeholder="Enter Phone Number" />
<div class="alert alert-danger" *ngIf="loginForm.get('phonenumber').hasError('required') && loginForm.get('phonenumber').touched">
Phone Number is required
</div>
<br />
<button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
</form>
También hemos puesto mensajes de error para los campos de correo electrónico y número de teléfono. Además, ese botón de envío solo se habilitaría cuando el formulario sea válido. El envío del formulario se maneja como se muestra en la lista a continuación:
loginUser() {
console.log(this.loginForm.status);
console.log(this.loginForm.value);
}
Si el formulario es válido en la consola del navegador, obtendrá el resultado de la siguiente manera:

Además, si hay un error, el botón Enviar se deshabilitará y se mostrará un mensaje de error como se muestra a continuación:

Puedes aprender a crear validadores personalizados para formularios reactivos Angular aquí.
Ahora supongamos un escenario en el que tiene un botón de opción para enviar una notificación. El usuario debe poder seleccionar la opción de enviar notificación y, en base a eso, cierto FormControl tendrá alguna validación.
Considere el siguiente formulario,

Hemos agregado una opción de Enviar notificación. Si el usuario selecciona Teléfono para enviar la notificación, el campo Número de teléfono debe ser obligatorio, de lo contrario, no debería ser así. Para lograr esto necesitamos realizar las siguientes tareas,
- Escuchar los cambios
- Put conditional validation
Para empezar, permítanos modificar nuestro formulario para manejar la notificación. Por lo tanto, ahora el formulario tiene una notificación FormControl con el valor predeterminado establecido en null, como se muestra en la lista a continuación:
this.loginForm = this.fb.group({
email: [null, Validators.required],
password: [null, [Validators.required, Validators.maxLength(8)]],
phonenumber: [null],
notification: ['email']
});
En la plantilla de formulario reactivo, agregaremos un grupo de botones de opción para manejar la opción Enviar notificación.
<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
<input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
<div class="alert alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
Email is required
</div>
<input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
<input formControlName='phonenumber' type="text" class="form-control" placeholder="Enter Phone Number" />
<div class="alert alert-danger" *ngIf="loginForm.get('phonenumber').hasError('required') && loginForm.get('phonenumber').touched">
Phone Number is required
</div>
<br />
<label class='control-label'>Send Notification</label>
<br />
<label class="radio-inline">
<input type="radio" value="email" formControlName="notification">Email
</label>
<label class="radio-inline">
<input type="radio" value="phone" formControlName="notification">Phone
</label>
<br />
<button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
</form>
En este punto de forma, se ve como se muestra a continuación:

Suscríbete a valueChanges
En los formularios reactivos, tanto FormControls como FormGroups tienen un método valueChanges. Devuelve un tipo observable, por lo que puede suscribirse a él, para trabajar con el cambio de valor en tiempo real de FormControls o FormGroups.
En nuestro ejemplo, necesitamos suscribirnos a valueChanges de la notificación FormControl. Esto se puede hacer de la siguiente manera:
formControlValueChanged() {
this.loginForm.get('notification').valueChanges.subscribe(
(mode: string) => {
console.log(mode);
});
}
Necesitamos llamar a esto un gancho de ciclo de vida de OnInit que se muestra a continuación:
ngOnInit() {
this.loginForm = this.fb.group({
email: [null, Validators.required],
password: [null, [Validators.required, Validators.maxLength(8)]],
phonenumber: [null],
notification: ['email']
});
this.formControlValueChanged();
}
Ahora, cuando cambie la selección de notificación en el formulario en la consola del navegador que puede ver, tiene el valor más reciente.

Tenga en cuenta que no estamos manejando ningún evento en el botón de opción para obtener el valor más reciente. Angular tiene un método valueChanges que devuelve el valor reciente como observable en FormControl y FormGroup, y estamos suscritos a él para el valor reciente en la notificación FormControl.
Conditional Validation
Nuestro requisito es que cuando la notificación se establece en teléfono, el campo FormControl de número de teléfono debe ser obligatorio y si se establece en correo electrónico, el número de teléfono FormControl no debe tener ninguna validación.
Modifiquemos la función formControlValueChnaged() como se muestra en la siguiente lista para habilitar la validación condicional en FormControl de número de teléfono.
formControlValueChanged() {
const phoneControl = this.loginForm.get('phonenumber');
this.loginForm.get('notification').valueChanges.subscribe(
(mode: string) => {
console.log(mode);
if (mode === 'phone') {
phoneControl.setValidators([Validators.required]);
}
else if (mode === 'email') {
phoneControl.clearValidators();
}
phoneControl.updateValueAndValidity();
});
}
Hay muchos códigos arriba, así que hable línea por línea.
- Uso del método get de FormBuilder para obtener una instancia del número de teléfono FormControl
- Suscribirse al método valueChanges en la notificación FormControl
- Comprobación del valor actual de la notificación FormControl
- Si el valor actual es phone, utilice el método setValidators de FormControl para establecer el validador necesario en el control de número de teléfono
- Si el valor actual es correo electrónico, utilice el método clearValidators de FormControl para borrar toda la validación en el control de número de teléfono
- En la última llamada al método updateValueAndValidity para actualizar las reglas de validación de phonecontrol
Ejecute la aplicación y verá que a medida que cambia el valor de la notificación, se cambia la validación del número de teléfono,

Mediante el uso de la potencia del método valueChanges de Angular formulario reactivo, puede lograr validaciones condicionales y muchas otras funcionalidades, como reaccionar a los cambios en el modelo de datos subyacente del formulario reactivo.
¿Te ha gustado este post?
Si te ha gustado este post, compártelo. Además, si aún no has echado un vistazo a nuestra biblioteca, ¡asegúrate de hacerlo! ¡Es la caja de herramientas más completa con componentes de interfaz de usuario basados en materiales, la cuadrícula de datos de Angular más rápida del mercado y 60+ gráficos de alto rendimiento!
