Angular Form Control: valid vs invalid
Profundiza en los estados de los controles de los formularios en Angular
En este post, vamos a ver la diferencia entre valid
e invalid
cuando tratamos con controles de formularios (Form Control
) y por qué cuando hacemos validaciones asíncronas, podemos estar usándolos mal.
Estados de los controles
Una de las propiedades interesantes de un Control
es el estado (status
), que nos permite saber el estado de validación del mismo. Pueden ser:
El estado PENDING
sólo aparece cuando tenemos validaciones asíncronas, y ahí es donde debemos saber bien la diferencia entre valid
e invalid
.
Aparte de este type
, en el API del Form Control
tenemos propiedades que retornan boolean
: valid
, invalid
y pending
.
Confusión usando valid/invalid
Una práctica muy común es querer mostrar un texto o desactivar un botón basado en el estado de nuestro control, es decir, usando estas propiedades. Por ejemplo, “Desactiva el botón de acción si existen errores de validación.” El código que implementaría esta expresión es el siguiente:
<button type="button" [disabled]="myControl.invalid">
Lo que literalmente dice, desactiva el botón si el control es inválido. Pues bien, en validaciones asíncronas eso no funciona como esperamos.
Escenario real
Puedes abrir el enlace (https://angular-valid-invalid-reactive-forms.stackblitz.io/) para ver el ejemplo en stackblitz.
El primer input
, es de validación síncrona, puedes omitirlo ahora mismo, puesto que lo hemos incluido para poder realizar la comparación. El segundo input
, tiene una validación asíncrona la cual dispara un error si el nombre que introducimos es “Alejandro”, para cualquier otro nombre, no dispara ningún error.
Además, existen dos botones, los cuales usan [disabled]
, uno usando valid
y otro invalid
. Se puede observar que uno funciona tal y como se espera pero el otro tiene un comportamiento no deseado.
Observe la siguiente imagen, la validación se encuentra en el estado PENDING
, y por tanto, sabemos que fallará. No obstante, el botón de más abajo no se encuentra deshabilitado porque está haciendo uso de la propiedad invalid
, mientras que el primero usa la propiedad valid,
el cual síque está desactivado mientras se realiza la evaluación.
Razonamiento
Esto ocurre porque el estado INVALID
sólo se produce cuando la validación ha terminado, y es inválida, errónea. Mientras que el estado VALID
sólo se produce cuando la validación ha terminado y es válida, sin errores.
Cuando se está evaluando la validación, podemos decir que no es ni válido, ni es inválido, por lo que la negación [disabled]="myControl.invalid"
no es cierta, porque para ser inválida, debe de haber terminado la validación, y no encontrarse en el estado PENDING
.
Esto puede romper la experiencia de usuario si la llamada al servidor toma más tiempo de la cuenta y el usuario hace click para enviar el formulario y no se lo impedimos.
Por esta razón, para este tipo de casos, siempre es mejor usar la negación de valid
quedando de la siguiente forma [dissabled]=”!myControl.valid"
. Aunque sepamos que una negación siempre es menos legible que una afirmación (tips de clean code), aquí hay un buen razonamiento de por qué usarlo así.
Feedback is welcome!
Se aprecia mucho obtener feedback, saber si este post gustó mucho o poco y también puedes escribirme comentarios y sugerencias para futuros posts.
Demo y Código: Link
Twitter: https://twitter.com/alejandrocoding
Otros posts: https://medium.com/@alejandrocoding