Validando formularios

En el artículo anterior vimos… Bueno, vimos bastantes cosas interesantes. Entre ellas, una forma de prevalidación de formularios muy tosca. El botón para grabar no estaba disponible hasta que habíamos cumplimentado todos los campos del formulario. Sin embargo, no es un sistema muy amigable. El usuario ve que el botón no está operativo, pero realmente no sabe por qué. No sabe si tiene que rellenar todos los datos, o si algunos son opcionales; los campos de password están con el contenido oculto (como todos los campos de tipo password); no sabe si es obligatorio marcar el checkbox de «mayor de edad»… En fin, que no le damos muchas pistas, y un usuario poco familiarizado con los formularios en Internet seguramente piense «Esta página no funciona» y salga para no volver a entrar.

Desde luego, no es la mejor solución. Ahora vamos a enfocarlo de otro modo. El botón siempre estará habilitado y, si el usuario lo pulsa sin tener bien cumplimentado algún campo importante, le informaremos de ello mediante un mensaje cómodo y amigable. De esta forma, le guiamos paso a paso, para rellenar correctamente nuestro formulario.

EN QUÉ CONSISTE LA VALIDACIÓN

Esto, que puede parecerles banal a algunos, es una cuestión que creo interesante comentar antes de empezar con este tema a nivel operativo. La validación tenemos que diseñarla nosotros antes de teclear una sóla línea de código. En concreto, tenemos que determinar lo siguiente:

  • Qué campos serán obligatorios, y cuales serán opcionales.
  • Cuál será la longitud mínima o máxima de un dato (en campos de texto).
  • Cuáles serán los valores mínimo y máximo en campos numéricos.
  • Cuantas opciones se podrán elegir, por ejemplo, en un selector múltiple.
  • Si el aviso de error se mostrará al pulsar un botón de envío (por ejemplo) o al abandonar un campo.
  • Y, en general, cualquier cosa que se nos ocurra como criterio.

Evidentemente, en casi la totalidad de los casos, las validaciones las aplicaremos sobre campos obligatorios. Si un campo es opcional, no tiene ningún sentido que le apliquemos reglas de validación.

Por lo tanto, vamos a empezar por diseñar el formulario, y sus reglas de validación. Yo, para este artículo, he diseñado un formulario bastante simple. Como nunca he sido buen dibujante, me vas a permitir que te muestre el resultado final, en lugar de los bocetos. Luego entraremos en programación.

Podría ser un formulario para que se registraran personas que, por ejemplo, optaran a algún concurso, o a un puesto de trabajo. Como ves, tiene cuatro campos, que vamos a hacer obligatorios, aunque los vamos a validar de distintos modos, para ver las distintas posibilidades. Así, el campo del nombre de usuario lo validaremos en tiempo real, según se teclea. En cambio, los campos de contraseña, repetición de la contraseña y la selección de idiomas hablados los validaremos cuando el usuario pulse el botón. Las reglas de validación serán las siguientes:

  • Para el nombre del usuario, es obligatorio teclear, al menos, cuatro caracteres. Le pondremos una limitación de un máximo de diez caracteres, aunque eso no pasará por validación, ya que el atributo maxlength de HTML limita físicamente el máximo de caracteres que se pueden teclear.
  • Para la contraseña pediremos un mínimo de seis caracteres, con una limitación máxima de diez.
  • Para la repetición de la contraseña se requerirá que el dato tecleado coincida con el del campo anterior.
  • Para la lista de idiomas hablados se requerirá que el candidato marque, al menos, tres de los que aparecen en la lista.

Veamos como montar todo el sistema de validaciones.

EL PRIMER CAMPO

El primer campo es el que más atención nos va a merecer aquí. Dado que queremos que se valide en tiempo real, eso ya nos dice que el proceso de validado puede hacerse en la vista. Vamos a ver como está declarado el campo en form04.component.html:

Como ves, hay varias cosas que ya connocemos, y otras que no tanto. Por ejemplo, vemos que hacemos doble binding con una propiedad llamada userName, que está definida en la lógica (form04.component.ts). Esto ya aprendimos como funciona en el artículo anterior. También vemos una línea con reeglas de validación. La regla required, que indica que es obligatorio cumplimentar el campo, es propia de HTML. También es el caso de la regla maxlength. Esta actúa físicamente sobre el campo, de modo que no nos va a permitir escribir más de diez caracteres, con lo cual ni siquiera tendremos que validar.

Otra cosa que nos llama la atención es el hecho de que el identificador Angular que le damos al campo (el que va precedido por #) hasta ahora nunca lo habíamos usado como una propiedad, asignádole un valor. Asumíamos que el propio identificador era el valor. Esto es así en otros casos, de los que ya hemos visto ejemplos, pero, además, permite una asignación, como en este caso específico. Al asignarle ngModel estamos diciéndole que, cuando se haga el binding hacia abajo del valor del campo se valide este conforme a las reglas de validación expresadas.

Vamos a darle una vuelta a este punto, porque, al principio, cuesta un poco familiarizarse con él. Cuando asignamos al identificador el valor ngModel al identificador del campo (en este ejemplo, userNameModel) se le crea, automáticamente, una propiedad llamada errors. Esta contiene unos valores booleanos por cada regla de validación que hayamos especificado para comprobar. Por ejemplo, hemos especificado que el valor de este dato deberá tener una longitud mínima de cuatro caracteres. Bien. Pues esto le crea a userName una propiedad errors, con una propiedad minlength. Si el valor tiene menos de cuatro caracteres, este flag se activa, pasando a valer true. Cuando el valor tiene más de cuatro caracteres, la propiedad userNameModel.errors.minlength valdrá false.

Además, se crea una propiedad llamada invalid (realmente userNameModel.invalid), que se pone a true si el campo es inválido, es decir, si rompe alguna de las reglas de validación. También se le crea una propiedad dirty (userNameModel.dirty), que se pone a true cuando se cambia por primera vez el valor del campo. Así mismo, se crea una propiedad touched (userNameModel.touched), que se pone a true la primera vez que se saca el foco del campo (evento blur). Y todo esto se crea y se gestiona automáticamente (Angular se ocupa de ello). Nosotros sólo tenemos que leer el valor de esas propiedades para determinar si están a true o a false, es decir, ver que estas propiedades nos informen de que se ha roto alguna de las reglas de validación.

Para ver estas propiedades, y el resultado de la validación, nos vamos un poco más abajo, al siguiente fragmento de la vista:

Lo que hacemos es crear una capa con las clases de bootstrap que le dan el color rojo de error, conteniendo los mensajes de los errores encontrados en el formulario. La existencia de esta capa en el DOM está supeditada, por una parte, a la variable mensajeDeError, que se actualizará cuando pulsemos el botón. Eso lo veremos en seguida. También está supeditada a que se detecten las propiedades userNameModel.invalid y userNameModel.touched, que ya sabemos que son actualizadas, en tiempo real, por Angular.

En la capa se avisa, entre otras cosas, de errores en la contraseña o en la lista de idiomas seleccionados. En eso no vamos a fijarnos por ahora. Lo que nos importa es el mensaje relativo al nombre de usuario, que se muestra si no cumple las reglas de validación. La validación de este campo se efectúa, por lo tanto, en la vista en tiempo real. No es necesario pulsar el botón para que se haga esta comprobación.

ATENCIÓN. Si hubiéramos creado el proyecto con el modificador --minimal true, de modo que la vista estuviera como un template dentro de la lógica del componente, a la etiqueta que abre el formulario deberíamos haberla inicializado con una asignación a otra directiva de Angular, llamada ngForm. En lugar de abrirlo así:

<form>

deberíamos haberlo abierto así:

<form #miFormulario="ngForm">

Esta es otra razón para no usar el modificador --minimal true al crear un proyecto.

 

ATENCIÓN. Es posible que el editor de VSC te marque cómo erróneas las lecturas de las propiedades userNameModel.errors.required y userNameModel.errors.minlength. Habiendo definido en el campo las validaciones required y minlength no hay tal error. Es sólo cosa del VSC. Ignora el aviso y, cuando ejecutes la aplicación, verás que no hay ningún problema. Incluso, durante la ejecución puedes abrir la consola del navegador, y verás que queda limpia, sin errores. Es una pequeña debilidad de VSC, algo molesta visualmente, pero no tiene importancia.

EL RESTO DE LOS CAMPOS

El resto de los campos no tienen montado este mecanismo. Se validan en un método de la lógica, cuando se pulsa el botón. Conceptualmente es mucho más simple, por lo que yo prefiero este último sistema. De hecho, sólo he usado la validación en tiempo real en el primer campo para que veas como se hace, y para que si encuentras código como ese, sepas lo que se está haciendo. Es posible que, en algún proyecto tuyo necesites una validación en tiempo real en la vista. pues ya sabes como hacerlo.

Cuando se pulsa el botón, se ejecuta una función que comprueba si alguna de las variables que reciben los valores de los campos no se ajusta a lo que deseamos, y muestra la capa roja de error. Si todos los campos están bien, se muestra una capa verde, indicando que todo ha ido bien. No vamos a detallar aquí la lógica, porque es, como verás en seguida que mires el código, extremadamente simple. La parte compleja de este ejercicio ya la hemos visto en el primer campo.

CONCLUYENDO

Como ves, se puede hacer una validación muy interesante. Además, cuando juegues con este formulario vas a comprobar otro punto que, aunque no tiene nada que ver con la valaidación, estrictamente hablando, es interesante, porque Angular nos facilita una tarea que, de otra forma, es más laboriosa. Se trata del selector múltiple. Si no seleccionas ningún valor, la variable que recibe a este campo tiene el valor undefined. Si seleccionas uno o más valores, la variable es una matriz con los elementos que corresponden a los valores de las opciones seleccionadas. Usando HTML convencional, sólo se lee el valor de la primera opción seleccionada, y hay que recurrir a JavaScript o jQuery, para leer toda la lista. Angular la lee directamente por nosotros, de forma automática. Otro punto a favor de Angular.

Como siempre, la aplicación en su estado actual, la tienes en este enlace. Analiza todo el código (en el artículo sólo lo he reproducido parcialmente, para no sobrecargarlo), para ver como funciona. No temas experimentar. Si rompes algo, y no sabes lo que ha pasado o como arreglarlo, siempre puedes volver a descargarte la aplicación.

   

Deja un comentario