Validación de formularios

publicado en la categoría JavaScript
Aunque la verificación final de los datos enviados desde un formulario debe ser hecha en el servidor que los procesará, siempre es bueno realizar una validación previa con JavaScript y así reducir los accesos y evitar el envio de datos vacíos o nulos.

Validar un formulario significa verificar que al enviarlo, todos los datos existan y estén dentro de los parámetros que hemos establecido.

La validación la hacemos con JavaScript para reducir el acceso al servidor que es quien seguramente procesará esos datos pero, esto no implica que, por razones de seguridad, allí no deban volver a verificarse.

En términos generales, podemos validar los datos agregando un atributo onsubmit en la etiqueta form o un atributo onclick en un botón. En ambos casos, llamaríamos a una función propia que evaluaría cada uno de los datos y actuaría en consecuencia.

Supongamos un ejemplo de este tipo:

<form name="formulario" action="#" onsubmit="return validar()" method="post">
	<input type="text" name="ingresos">
	<input type="submit" value="enviar">
</form>

La forma tradicional de leer los datos es usar el atributo name para referenciar los objetos:

document.forms["formulario"]; // es la etiqueta form
document.forms["formulario"]["ingresos"]; // es la etiqueta input

Perp si definimos atributos id como en cualquier otra etiqueta, todo es más fácil:

<form id="formulario" action="#" onsubmit="return validar()" method="post">
	<input type="text" id="ingresos">
	<input type="submit" value="enviar">
</form>

La función simplemente verifica que haya un texto y si no lo hay devuelve false y de ese modo, no se enviaría:

function validar() {
	var elINPUT = document.getElementById("ingresos");
	var datos = elINPUT.value;
	if (datos===null || datos===""){
        	alert("faltan datos");
		return false;
	}
}

Lo mismo podríamos hacer con cualquier otro dato pero el HTML5 nos provee de un atributo que facilita esas verificaciones, dejándolas en mano del navegador.

Una de ellas es el atributo required que nos mostrará un mensaje de advertencia si se intentan enviar datos vacíos:

<input type="text" id="ingresos" required />

Comparemos el resultado en estos ejemplos; el primero es normal y el segundo utiliza required:

Como se ve, en el primero pueden enviarse datos vacíos y en el segundo no.

El estilo con que cada navegador muestra esos campos erróneos varía y para controlarlos se debe usar la pseudo-clase :required.

Actualmente, los formularios se han simplificado, basta usar un botón de envío con la etiqueta button que nos ofrece más posibilidades gráficas ya que los navegadores no le asignan propiedades por defecto y nos da la posibilidad de agregar textos simples, formateados o imágenes.

No todas las etiquetas de formularios deben estar dentro de form ni deben ser usadas para enviar o recibir datos desde algún otro servidor. Muchas veces las podemos usar de manera independiente por ejemplo, para ejecutar funciones de JavaScript.

<input type="text" id="ejemplotxt" placeholder="validar texto" required>
<button onclick="validar('ejemplotxt')">enviar</button>

En ese caso, la validación puede hacerse con la función checkValidity():

function validar(id) {
	var elINPUT = document.getElementById(id);
	if (elINPUT.checkValidity()===false) {
		alert(elINPUT.validationMessage);
		return;
	}
	alert("TEXTO ENVIADO: " + elINPUT.value);
}

En el ejemplo, al querer enviar el dato haciendo click en el botón, se ejecuta una función que verifica que haya algún dato y para eso simplemente se evalua el valor de su propiedad checkValidity() que será false si no hay un dato o true si lo hay. Si no escribimos nada, la ventana de alerta nos mostrará el texto Complete este campo.

En los diferentes tipos de etiquetas input hay otros atributos que también indican los datos obligatorios o los valores aceptados tales como max y min.

Si usáramos una etiqueta input de tipo number:

<input type="number" min="10" max="20" id="ejemplonum" placeholder="validar número" required>
<button onclick="validar('ejemplonum')">enviar</button>

En este caso, no sólo se verificará que haya un dato sino que ese dato esté en el rango establecido por min y max. Si escribiéramos un valor mayor a 20, la ventana de alerta nos mostrará el texto Seleccione un valor que no sea más de 20.

Cada uno de esos textos de errror son definidos por el navegador de modo automático y accedemos a ellos a través de la propiedad validationMessage.

Otro atributo que se ha incorporado es pattern que nos permite definir aún más el tipo de dato que esperamos que se ingrese. El valor a usar es una expresión regular; por ejemplo:

pattern=".{4}" el texto debe tener cuatro caracteres
pattern=".{6,}" el texto debe tener seis o más caracteres
pattern=".{4,6}" el texto debe tener entre cuatro y seis caracteres
pattern="[A-Za-z]{4,6}" el texto solo debe contener letras
pattern="[0-9,a-z]{4,6}" solo números o letras en minúscula entre cuatro y seis caracteres

Hay otras propiedades que pueden ser consultadas; por ejemplo, willValidate devuelve true si la etiqueta debe ser validad y false si no debe serlo.

La propiedad validity es un dato de tipo objeto que contiene referencias a los distintos errores que pueden evaluarse y cada uno de ellos tendrá un valor de false o true:

badInput el navegador no puede evaluar el dato
customError es true cuando se establece un tipo me error personalizado
patternMismatch el dato no coincide con los límites establecidos por el atributo pattern
rangeOverflow el valor es mayor que el indicado en el atributo max
rangeUnderflow el valor es menor que el indicado en el atributo min
stepMismatch el valor no coincide con el indicado en el atributo step
tooLong el dato excede la longitud establecida en el atributo maxlength
typeMismatch el tipo de dato no se coincide con el atributo type
valid será true sólo si el dato es válido
valueMissing falta el dato cuando se usa el atributo required

Entonces, en el primer ejemplo, elINPUT.validity.valueMissing será true y en el segundo ejemplo, elINPUT.validity.rangeOverflow será true. En ambos casos, todos los demás serán false.

Si se usa jQuery deberemos acceder a checkValidity() de modo indirecto; por ejemplo, agregando una función:

$.fn.isValid = function(){
	return this[0].checkValidity()
}

// que podríamos usar de este modo:
if($('#ejemplo').isValid(){
	// ingresos válidos
} else {
	// ingresos inválidos
}