Contenido

Validar formularios con jQuery

25 Jun

+ 31

Hace unas semanas tuve que desarrollar una función que me permitiera validar formularios mediante Javascript de una forma fácil y rápida. Tenía que ser con jQuery por que es el framework que estamos usando ahora en el trabajo. Una de las premisas era que debido a la aplicación y a la tecnología, necesitaba que fuera lo más flexible posible, por ese motivo opté por el siguiente código:

El código

//Filtros
var filters = {
    requerido: function(el) {return ($(el).val() != '' && $(el).val() != -1);},
    email: function(el) {return /^[A-Za-z][A-Za-z0-9_]*@[A-Za-z0-9_]+\.[A-Za-z0-9_.]+[A-za-z]$/.test($(el).val());},
    telefono: function(el){return /^[0-9]*$/.test($(el).val());}};
// Extensiones
$.extend({
	stop: function(e){
        if (e.preventDefault) e.preventDefault();
        if (e.stopPropagation) e.stopPropagation();
    }
});
// Código
$(document).ready(function(){
	$("form.validable").bind("submit", function(e){
		if (typeof filters == 'undefined') return;
	    $(this).find("input, textarea, select").each(function(x,el){
	        if ($(el).attr("className") != 'undefined') {
	        $.each(new String($(el).attr("className")).split(" "), function(x, klass){
	            if ($.isFunction(filters[klass]))
	                if (!filters[klass](el))  $(el).addClass("error");
	        });
	        }
	    });
		if ($(this).find(".error").size() > 0) {
			$.stop(e || window.event);
			return false;
		}
	    return true;
	});
});
	

Explicación

Si no fijamos en el código podemos ver que este script, será ejecutado en cuando el contenido de la página esté completamente cargado, esto lo conseguimos gracias a $(document).ready(); que jQuery nos ofrece.

Una vez cargado el contenido, se encargará de recorrar todos los elementos y buscará todos los elementos <form class="validable">, a los que le añadirá un listener que será ejecutado en el momento que el formulario ejecute el método submit().

En ese momento, el script recoge todos los element <input />, <textarea /> y <select /> del formulario y revisa las clases de cada elemento. Dependiendo de la clase y si está está definida en el objeto filters, realizará una comprobación u otra.

El objeto filters, se compone de una serie de métodos que serán lanzados para validar cada uno de los elementos, por ejemplo:

//HTML
<input type="text" name="prueba" value="" class="requerido email noanieto" />

//Javascript (Filtros)
var filters = {
       requerido: function(el) {return ($(el).val() != '' && $(el).val() != -1);},
       email: function(el) {return /^[A-Za-z][A-Za-z0-9_]*@[A-Za-z0-9_]+\.[A-Za-z0-9_.]+[A-za-z]$/.test($(el).val());},
       noanieto: function(el){return !"anieto".indexOf($(el).val());}
}

Como podemos ver el elemento <input />, le estamos indicando que es del tipo requerido, email y noanieto. Validaciones que definimos en el objeto filters. En caso de no existir una de las clases indicadas en el elemento <input /> (o cualquier otro), esta será omitida.

Si el elemento no cumple una de las condiciones, añadiremos una clase más al elemento (class="error") y pararemos la ejecución del submit().

Demo

He montado una pequeña demo para verlo funcionar. La podeis probar aqui.

Aclaraciones

Está claro que se trata de una validación Javascript y que su única función es mejorar la experiencia del usuario evitando que llegue a submitar una página con datos erroneos, para hacer las cosas bien, la página receptora, debería hacer la misma comprobación y devolver a la página anterior en caso de error, así los usuarios que no tengan la capacidad de ejecutar javascript, tendrán un resultado igual a los que sí, aunque tengan que esperar a la carga de la página.

Versión para MooTools

Epplestun, me pasa una adaptación del script para MooTools. Muchas gracias!!!

$(document).addEvent('domready', function() {
       $(document.body).getElements('form.validable').addEvent('submit', function(e) {
               if (typeof filters == 'undefined')
                       return;

          this.getElements("input, textarea, select").each(function(el) {
               if (el.getProperty("class").length) {
                       el.removeClass("error");
                               el.getProperty("class").split(" ").each(function(filtro) {
                                       if (!filters[filtro](el))
                                               el.addClass("error");
                               });
               }
          });

          this.getChildren().each(function(el) {
               if(el.hasClass("error")) {
                               e = new Event(e);
                               e.stop();
                       return false;
               }
          });

          return true;
       });

Mm… algo así venia buscando hace un tiempo para una web. Quería evitar tardar demasiado con el formulario.
Me gustaría que me explicases el filtro

noanieto: function(el){return !”anieto”.indexOf($(el).val());}

gracias, como siempre

@Manuchis: Te explico, devuelve false en caso de encontrar la palabra “anieto” dentro del value del elemento.

Existe un plugin, JQuery.validate(), que es bastante configurable (todos los validators son externos) y potente a la vez que simple.

Como siempre excelente el tutorial. Muchas gracias

@Blaxter: Si, lo conozco aunque no lo he usado. Cuando lo vi me pareció bastante poco flexible y complicado para que lo use gente que no controla de Javascript.

Excelente, sencillamente practico y flexible, ahora que estoy empezando a utilizar jQuery me sirve para dar mis primeros pinitos!! Gracias!!

Muy interesante. Lo que no me ha gustado es eso de “submitar”, podrías haber usado enviar.

Muy bueno la verdad, jeje y para los que les den a MooTools como yo dejo aquí la versión del validable.js en MooTools :-) , en los filtros en lugar de usar $(el).val() se ha de utilizar $(el).value y listo, funciona :-D

$(document).addEvent('domready', function() {
	$(document.body).getElements('form.validable').addEvent('submit', function(e) {
		if (typeof filters == 'undefined')
			return;

	   this.getElements("input, textarea, select").each(function(el) {
	   	if (el.getProperty("class").length) {
	   		el.removeClass("error");
				el.getProperty("class").split(" ").each(function(filtro) {
					if (!filters[filtro](el))
						el.addClass("error");
				});
	   	}
	   });

	   this.getChildren().each(function(el) {
	   	if(el.hasClass("error")) {
				e = new Event(e);
				e.stop();
	   		return false;
	   	}
	   });

	   return true;
	});
});

Excelente, super simple y limpio.

Gracias.

Fácil, rápido y para toda la familia, jejejeje.

Me encanta tu blog. Felicidades!!!

excelente, me encanta el funcionamiento, yo usaba algo parecido usando expresion regulares en el atributo rel http://refactormycode.com/codes/149-simple-form-validator-with-regex (igual te sirve para ampliar el tuyo) permitiendo engachar una función para casos en los que no me servian expresiones regulares.

¿Se puede usar/extender este script libremente?

Un saludo

@jdeveloper: Me gusta la idea, le echaré un vistazo.

Puedes usar/extenderlo lo que tu veas ;)

Gracias

Andrés gracias por poner el codigo legible jejeje :-)

Excelente validador, y excelente blog :)

He estado haciendo pruebas con él y he visto un error, que a mi al menos me salía, en la línea:

$.stop(e || window.event);

Lo he solucionado poniéndolo de la siguiente forma:

$(this).stop(e || window.event);

Saludos,

Muy buena guía, muchas gracias.
Me ha sido muy práctica.
Saludos.

Hola, esta genial el tutorial. Lo tengo ya funcionando perfectamente pero queria saber si hay algun modo para lanzar mensajes de error. A ser posible todos los mensajes en la misma capa/lugar.

gracias!!

Hola, excelente artículo.

Yo lo extendí un poco para adaptarlo a mi web, pero debido a que soy nuevo en el uso de jquery, me he liado un poco al querer pasarlo a plugin, para dejarlo en el fichero .js común del sitio. Si pudieras darme una pista te estaría muy agradecido.

Saludos.
Siempre eres un gran aporte. :-)

Joer, Andres: ose que ’submitar’ ¿eh?. Ya te vale :D

Hola, muy bueno, lo estoy implementando en una aplicacion que estoy desarrollando, pero hay un tema, cuando tengo un select con la class requerido, y no selecciono nada, no me agrega la class error

hola, muchisimas gracias por el aporte. solo veo que se le pueden agregar numeros a un nombre de persona. estaria bien si fuese para un nombre de usuario. por lo demas esta muy bien.

@ignacio: La gracia está en el que la validación es externa y las condiciones que debe cumplir un <input /> las pones tu. Así que puedes validar cualquier tipo de condiciones. :D

Hola,

He estado probando este código pero cuando me encuentra un error, aunque lo corrija sigue mostrándome que está erroneo.
Como lo podría solucionar?
Muchas gracias de antemano.

@Pico: Agradecería que fueras algo más específicico ya que un error puede ser cualquier cosa y en cualquier lugar.

Por cierto, volviendo a revisar este post, me he dado cuenta de un fallo jejejejeje, se trata del filtro de validación de email, ya que si tenemos un correo tal que: eppl.estun@loquesea.com, no permite validar nombres de usuario compuestos por .

La solución y expresión regular correcta sería:
/^[A-Za-z\.][A-Za-z0-9_\.]*@[A-Za-z0-9_]+\.[A-Za-z0-9_.]+[A-za-z]$/

@epplestun: Tienes razón, aunque esto debe de servir únicamente como ejemplo ya que tampoco permite los email con dominios con – (guión) y algunas combinaciones más.

Simplemente es para ilustrar y cada uno debería definir los filtros que considere oportunos :D

Gracias por el aviso, saludos

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.