miércoles, 26 de octubre de 2011

jquery.validation o cómo validar tus formularios

Llevo mucho tiempo queriendo hincar el diente al plugin de jQuery, jquery.validation.

Como desarrollador de programas de gestión, el validar formularios es una tarea obligada y repetitiva. Siendo así quiero abandonar mis actuales métodos manuales de validación y adoptar una nueva mecánica de validación cuyo código sea más limpio, compacto y extensible.

Buscando en Internet, todas las pistas nos conducen a jquery.validation (curioso que después el fichero javascript se llame jquery.validate, pero bueno…). De hecho, incluso Microsoft y sus proyectos ASP.NET MVC3 delega las tareas de validación en este plugin en detrimento de sus propias librerías de scripting a las que ya no da soporte.

Cabe mencionar que la utilización de jquery.validation en proyectos de tipo ASP.NET WebForms se complica un poco por la capa de abstracción que agrega esta tecnología y la imposición de que cualquier página debe y sólo puede tener un formulario. Siendo así, los ejemplos de este post están plenamente enfocados a páginas web sin tener en cuenta el lado del servidor. Es decir, este post servirá a desarrolladores de ASP.NET, de PHP, etc. Todo ello porque nos quedamos en el lado cliente y no nos importa el lado del servidor.

Instalación

El primer e ineludible paso es descargar el plugin.

La página oficial es http://bassistance.de/jquery-plugins/jquery-plugin-validation/ que finalmente redirecciona a http://jqueryvalidation.org/

Si trabajas con Visual Studio puedes descargar el paquete a través de NuGet, que resulta más cómodo y además incluye las dependencias necesarias, que en nuestro caso es solamente la librería jQuery.

La documentación sobre el plugin está disponible en http://rocketsquared.com/wiki/Plugins/Validation

Para comenzar a utilizar jquery.validation, simplemente debemos agregar una referencia a las librerías jQuery y jquery.validation en nuestra página.

    <script src="Scripts/jquery-1.6.4.js" type="text/javascript"></script>

    <script src="Scripts/jquery.validate.js" type="text/javascript"></script>


Conceptos básicos

Si trabajamos con jquery.validation hay que tener claros que son los métodos de validación y las reglas de validación.

Los métodos de validación implementan el código necesario para validar un elemento.

De serie tenemos disponibles un número considerable de métodos de validación para las comprobaciones más habituales, pero siempre es posible agregar a jquery.validation nuestras propias validaciones personalizadas.

Por ejemplo, un método de validación sería el código necesario para validar que la entrada es numérica.

Por otro lado, las reglas de validación permiten asociar un elemento de nuestro formulario a uno o más métodos de validación.

Para asociar una regla de validación a un elemento, podemos hacerlo de las siguientes formas que no son excluyentes y pueden combinarse según nuestras necesidades:

  • A través de nombres de clases css en atributo class. Por ejemplo class=”required number” especifica que nuestro elemento será requerido y sólo aceptará números.
    • Por supuesto, estos nombres de clases no tienen por qué existir en tu hoja de estilos, son clases que utilizará sólo jquery.validation.
  • Con atributos personalizados que requieren parámetros. Por ejemplo <input type=”text” minlength=”3”>, especifica que el contenido de nuestra caja de texto no debería ser menor a 3 caracteres
  • A través de código javascript y añadiendo las reglas a través del objeto rules.

Un primer ejemplo

Con este primer ejemplo romperemos el hielo.

    <form method="post" id="myForm">

    <p>

        Nombre

        <input type="text" id="nombre" name="nombre" class="required" />

    </p>

    <p>

        Edad

        <input type="text" id="edad" name="edad" class="required digits" />

    </p>

    <p>

        <input type="submit" value="Enviar" />

    </p>

    </form>

    <script type="text/javascript">

        $().ready(function () {

$("#myForm").validate({ debug: true });

        });

    </script>


En este formulario cabe reseñar lo siguiente:

  • Hemos especificado las reglas de validación a través de nombres de clases.
  • Hemos llamado al método validate() para el elemento myForm, que configura el formulario para que sea validado.
    • Además hemos especificado que estamos en depuración para que el formulario no sea enviado. Lógicamente, en producción no tendremos activado este parámetro.
  • A partir de este momento, el formulario no podrá ser enviado si no cumple con nuestras reglas impuestas.

Si ampliamos el ejemplo anterior para que el nombre tenga al menos 2 caracteres y la edad esté comprendida entre 18 y 99 años, tendremos que especificar estas reglas de validación a través de atributos con parámetros:

<form method="post" id="myForm">

<p>

    Nombre

    <input type="text" id="nombre" name="nombre" class="required" minlength="2" />

</p>

<p>

    Edad

    <input type="text" id="edad" name="edad" class="required digits" min="18" max="99" />

</p>

<p>

    <input type="submit" value="Enviar" />

</p>

</form>


Si no nos gusta especificar las reglas de validación a través de nombres de clases o atributos con parámetros, podemos utilizar javascript para acceder al objeto rules y meterlas por código:

    <form method="post" id="myForm">

    <p>

        Nombre

        <input type="text" id="nombre" name="nombre" />

    </p>

    <p>

        Edad

        <input type="text" id="edad" name="edad" />

    </p>

    <p>

        <input type="submit" value="Enviar" />

    </p>

    </form>

    <script type="text/javascript">

        $().ready(function () {

            $("#myForm").validate({

                debug: true,

                rules: {

                    nombre: {

                        required: true,

                        minlength: 2

                    },

                    edad: {

                        required: true,

                        digits: true,

                        min: 18,

                        max: 99

                    }

                }

            });

        });

    </script>


Mensajes de error

Algo importante cuando validamos, es cómo y dónde se muestran los mensajes de error.

Cuando sucede un error durante la validación, por defecto jquery.validation agrega dinámicamente una etiqueta label a continuación del campo validado. Además, el mensaje de esta etiqueta es igualmente predefinido y está en inglés.

clip_image001

clip_image002

En lo relativo al nuevo elemento label creado, es posible especificar el tipo de elemento que queremos crear para mostrar un error, en qué lugar del documento queremos que aparezca, mostrar resúmenes de errores para agrupar los mensajes, etc.  Lo cierto es que el plugin jquery.validation es muy configurable y se puede hacer con él casi cualquier cosa.

En un punto siguiente en este mismo post, daré unas breves indicaciones de cómo personalizar este mensaje (digo breves porque si no este post sería infinito y lo que pretendo es que sea una introducción a jquery.validation).

Lo que sí me parece muy importante es la traducción del mensaje. Después de todo, de poco serviría este plugin si los mensajes fueran hardcode.

La forma más sencilla de traducir los mensajes es bajarse la traducción de los mismos al lenguaje que necesites. Por defecto, jquery.validation está traducido a más de 41 idiomas, pero si aun así tu idioma no está disponible te resultará bastante sencillo traducirlo.

En la misma descarga del plugin hay una carpeta localization donde están todos los ficheros de idioma.

Si por ejemplo, queremos los mensajes en español bastaría con incluir la siguiente referencia a nuestra página, siempre después de la referencia a jquery.validation.

<script src="Scripts/messages_es.js" type="text/javascript"></script>


El contenido de este fichero es el siguiente:

/*

 * Translated default messages for the jQuery validation plugin.

 * Locale: ES

 */

jQuery.extend(jQuery.validator.messages, {

  required: "Este campo es obligatorio.",

  remote: "Por favor, rellena este campo.",

  email: "Por favor, escribe una dirección de correo válida",

  url: "Por favor, escribe una URL válida.",

  date: "Por favor, escribe una fecha válida.",

  dateISO: "Por favor, escribe una fecha (ISO) válida.",

  number: "Por favor, escribe un número entero válido.",

  digits: "Por favor, escribe sólo dígitos.",

  creditcard: "Por favor, escribe un número de tarjeta válido.",

  equalTo: "Por favor, escribe el mismo valor de nuevo.",

  accept: "Por favor, escribe un valor con una extensión aceptada.",

  maxlength: jQuery.validator.format("Por favor, no escribas más de {0} caracteres."),

  minlength: jQuery.validator.format("Por favor, no escribas menos de {0} caracteres."),

  rangelength: jQuery.validator.format("Por favor, escribe un valor entre {0} y {1} caracteres."),

  range: jQuery.validator.format("Por favor, escribe un valor entre {0} y {1}."),

  max: jQuery.validator.format("Por favor, escribe un valor menor o igual a {0}."),

  min: jQuery.validator.format("Por favor, escribe un valor mayor o igual a {0}.")

});


Una vez hemos traducido los mensajes predefinidos, podríamos querer mostrar mensajes personalizados o simplemente un mensaje especial para un campo concreto.

jquery.validation resuelve la búsqueda del mensaje a mostrar de la siguiente forma:

·         Primero busca si hemos especificado un mensaje para nuestro elemento a través de javascript. Si lo encuentra, este será siempre el mensaje mostrado. Con javascript podemos especificar un único mensaje para todos los errores de validación o afinar un mensaje por cada tipo de error de validación.

·         Segundo busca si nuestro elemento tiene definido el atributo title. Si lo encuentra, el valor del mismo será mostrado.

·         Por último, si no encuentra mensajes desde javascript ni el atributo title, buscará en los mensajes predefinidos.

Un ejemplo de personalización a través de javascript:

        $().ready(function () {

            $("#myForm").validate({

                debug: true,

                rules: {

                    nombre: {

                        required: true,

                        minlength: 2

                    },

                    edad: {

                        required: true,

                        digits: true,

                        min: 18,

                        max: 99

                    }

                },

                messages: {

                    nombre: {

                        required: "Nombre es obligatorio",

                        minlength: function (p, element) {

                            return "Nombre tiene que ser igual o mayor que " + p;

                        }

                    },

                    edad: "Este será el único mensaje para edad"

                }

            });

        });

 

Reglas y métodos de validación personalizados

Si no tenemos suficiente con las reglas y métodos de validación que incluye de serie jquery.validation, resulte muy sencillo implementar nuestra propia lógica de validación.

Por ejemplo, crearemos un regla que validará si el nombre suministrado es empleado o no de nuestra empresa.

La regla de validación la llamaremos esempleado y al método de validación le llamaremos esEmpleadoEmpresa. En la práctica, el método de validación suele llamarse igual que la regla de validación, pero en este ejemplo las he llamado distintas para que veas que no es necesario asociar una regla y su método por nombre.

// 1. DEFINIR NUESTRO MÉTODO DE VALIDACIÓN PERSONALIZADO

 

function esEmpleadoInterno(value, element, param) {

    //value es el valor actual del elemento que se está validando

    //element es el elemento DOM que se está validando

    //param son los parámetros especificados por el método

    //  p. ej. en el caso de minlength="3", param será 3

    //  en caso de que el método no tenga parámetros, param será true

    value = value.toLowerCase();

    if (value == "sergio" || value == "antonio" || value == "dani") {

        return true; //supera la validación

    }

    else {

        return false; //error de validación

    }

}

 

// 2. REGISTRAR REGLA DE VALIDACIÓN, MÉTODO DE VALIDACIÓN Y MENSAJE POR DEFECTO

 

$.validator.addMethod("esempleado", esEmpleadoInterno, "No eres empleado");

 

// 3. UTILIZAR NUESTRA NUEVA REGLA DE VALIDACIÓN

 

$().ready(function () {

    $("#myForm").validate({

        rules: {

            nombre: {

                esempleado: true

            }

        }

    });

});

 

Remote

Lo cierto es que remote es muy sencillo de entender. Simplemente delegamos la validación de nuestro elemento en una llamada a una url (servicio web, método de página, controlador genérico, etc.) que validará el valor en el servidor y tiene que devolver en formato JSON un true si la validación ha tenido éxito o false (o cualquier otro valor distinto de true) en caso contrario.

En ASP.NET (sin importar si hablamos de WebForms o de MVC) podríamos agregar por ejemplo un controlador genérico (.ashx) para llevar a cabo la tarea de validación en el servidor.

<%@ WebHandler Language="VB" Class="Remote" %>

 

Imports System

Imports System.Web

 

Public Class EsSergio : Implements IHttpHandler

   

    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

        context.Response.ContentType = "application/json"

        Dim js As New System.Web.Script.Serialization.JavaScriptSerializer

        Dim nombre As String = context.Request.QueryString.Item("nombre")

        If nombre = "Sergio" Then

            context.Response.Write(js.Serialize(True))

        Else

            context.Response.Write(js.Serialize(False))

            'context.Response.Write(js.Serialize("No eres Sergio"))

        End If

    End Sub

 

    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable

        Get

            Return False

        End Get

    End Property

 

End Class


Y el código javascript para necesario sería:

            $("#myForm").validate({

                rules: {

                    nombre: {

                        remote: "EsSergio.ashx"

                    }

                }

            });


Por defecto, remote hace una petición GET con los parámetros nombre=valor.

En cualquier caso, remote permite configurar todo lo que queremos la petición AJAX a través de su parámetro options.

Personalizando la validación

En este punto veremos opciones de personalización de jquery.validator que nos pueden ayudar a mejorar tanto nuestra experiencia como desarrolladores como la experiencia del usuario (muchas de estas opciones se pueden configurar tanto en setDefaults, en validate para la primera vez que configuramos el formulario como en siguientes llamadas a validate – accediendo después a settings – para modificar algo de un formulario ya configurado).

No pretendo poner un ejemplo sobre cada caso concreto, sino simplemente que sepas que se pueden hacer ciertas cosas y que sepas por dónde van los tiros.

submitHandler nos permite especificar una función que se llamará cuando la validación haya tenido éxito. En este función podemos incluir código de validación a nivel global y además será responsabilidad nuestra enviar definitivamente el formulario con form.submit().

invalidHandler es una función que se llamará si la validación no ha tenido éxito.

Con ignore podemos especificar un selector jQuery para ignorar campos de nuestro formulario.

onsubmit, onfocus, onkeyup, onclick nos permiten decidir cuándo se realizará la validación.

Con errorClass y validClass podemos especificar el nombre de la clase CSS que se agregará al elemento validado en caso de fracaso o de éxito de la validación.

Con errorElement, errorContainer, errorLabelContainer y wrapper podemos configurar la posición y que tipo de elementos se generarán para los mensajes de error.

showErrors es una función que nos permite tratar con todos los mensajes de errores encontrados para visualizar de una forma concreta o realizar la operación que creamos oportuna.

errorPlacement es una función que nos permite decidir donde situar los mensajes de error generados.

higlight y unhiglight determinan como resaltar los elementos que no han superado la validación.

Está claro que jquery.validation da para muchos posts, pero en mi caso hasta aquí ha llegado mi introducción a jquery.validation.

Espero que este post te haya servido al menos para que te pique el gusanillo y a partir de ahora valides mejor y de forma más mecánica tus formularios.

Un saludo!

43 comentarios:

  1. Muchas gracias por el aporte relamente me has sacado de un gran problema....

    ResponderEliminar
  2. Gracias por el comentario Mario, me alegro de haber ayudado.
    Un saludo!

    ResponderEliminar
  3. Gracias por el comentario, muy claro, debo preguntarle como haría para validar un textbox que está dentro de un listview cuando se antes de insertar el registro en la BD., no encuentro la solución. gracias desde ya

    ResponderEliminar
  4. y como le hago para enviar el formulario si ya esta validado

    ResponderEliminar
    Respuestas
    1. submitHandler: function()
      {
      document.miformulario.submit()
      //O con este codigo
      $("#miformulario").submit()
      }

      Eliminar
  5. Excelente publicación, me ha ayudado mucho

    ResponderEliminar
  6. Muchísimas gracias!!! no tienes idea cómo sufrí para colocar el texto de error donde yo quisiera, y era taaaan sencillo... Lo que es saber!

    ResponderEliminar
  7. Gracias por el excelente artículo. Es completo y aclara las formas de manejar las validaciones.

    ResponderEliminar
  8. Gracias nuevamente, estoy utilizando remote, y me aclaro mucho tu artículo, te pregunto porque se me presento el caso donde debo pasar dos parámetros al controlador genérico (.ashx), se puede?

    ResponderEliminar
  9. hola… ojala puedas responderme como hago para que la validación se ejecute al pulsar una imagen xq para grabar yo escribo esto: < a onClick="GrabarDatos(); return false" href="#" >< img src="imagen/grabar.jpg" title="Grabar" alt="Grabar" /> de antemano GRACIAS.

    ResponderEliminar
    Respuestas
    1. En la funcion que ejecutas al hacer click en la imagen puedes usar un if ($("#miformulario").valid()) asi ya estarias ejecutando la validacion al hacer click sobre tu imagen.

      Eliminar
  10. Sergio gracias como haces de facil la vida de los demas desarrolladores con una explicacion tan sencilla

    ResponderEliminar
  11. Me fue muy útil muchas gracias... excelente post

    ResponderEliminar
  12. Todo perfectamente claro, pero un detalle: ¿como validar la existencia de un resitro dentro de una tabla mysql, es decir, que busque si un numero telefonico existe por ejemplo o un codigo de material, etc.?

    vrozas2009@gmail.com

    ResponderEliminar
  13. Felicitaciones camarada sos un capo, yo ma havia olvidado de como hacer estos codigos, pero su claridad en la escrita fue de mucha ayuda

    ResponderEliminar
  14. Está bueno el tutorial, sin embargo, necesito saber como validar al hacer clic en una referencia definida asi:
    Regresar.

    Tengo que para accion click sobre la palabra regresar, se devuelva para digitar otro campo, por tato necesito validar al momento de clickear la palabra.

    Agradezco la ayuda que puedan prestarme lo antes posible.

    Muchas gracias

    ResponderEliminar
  15. Hola
    Muchas gracias. Me ha servido mucho el tutorial. Lo usé, pero debo hacer algo más y no he encontrado cómo.
    Necesito que los mensajes de error puedan ser leídos de archivos de texto plano. Se me había ocurrido hacerlo con un PHP. O sea, lo que necesitaría es que desde el JQueryValidate pueda, mediante un llamado AJAX, hacer la lectura de esos archivos y colocarlos como messages para JQueryValidate. La lectura de los archivos de texto y la invocación a AJAX se hace bien, pero no puedo setearle los mensajes al a las reglas correspondientes, porque el AJAX me ha quedado por fuera de las reglas, no sé dónde llamarlo realmente.
    ¿Alguna idea? Desde ya muchas gracias!!!
    Gustavo

    ResponderEliminar
  16. Muy buen tutorial mis felicitaciones, tengo un problema y es que tengo el jquery validate en un proyecto. me realiza las validaciones ajax sin problemas pero no me valida el restro de los campos requeridos, tengo a mayores una libreria jquery.jcombos que es para rellenar los selectores desde ajax, este puede ser el problema no son compatibles estas librerias. un saludo

    ResponderEliminar
  17. Hola buen post quisiera saber como usar ese validador usando un boton tipo BUTTON es que deseo encriptar mi password con javascript pero no me deja cada vez que cambio submit por button no se valida apesar que pongo dentro de una funcion soy nuevo en esto si tienes alguna salida si me puede orientar como poder hacerlo .... gracias desde ya !!!!! :)

    ResponderEliminar
  18. hola, me gustaria saber como puedo hacer para validar que los campos no se repita la informacion, osea lo contrario de equalsTo

    ResponderEliminar
  19. Buenos dias amigo,
    cómo hago para que me functiona con un botón tipo button y no tipo submit?
    Muchas gracias.

    ResponderEliminar
  20. Hola, muy bueno el tutorial con el primero que entendi como funciona este plugin. Mi consulta es la siguiente una vez que la validacion termino yo tengo creada una consulta en php para poder cargar los parametros, como hago para llamar ese archivo php

    ResponderEliminar
    Respuestas
    1. Amigo, yo te puedo ayudar, solo debes ser un poco más específico y mostrar un poco de tu codigo, más o menos creo saber lo que preguntas, pero aún no estoy completamente claro, con gusto puedo ayudar...

      Eliminar
  21. Exelente material, sigue así amigo, creo que realizaré algunos tutos potentes, a partir del conocimiento adquirido en este post, felicidades!!

    ResponderEliminar
  22. Cómo hacer que en función del lenguaje con el que se navega pueda desplegar los mensjes de error en uno u otro idioma. Alguna idea?

    ResponderEliminar
  23. Hola Aim,
    Yo lo que hago es cargar desde el servidor solamente el fichero .js de mensajes del idioma del usuario.
    Si no tuviera servidor, quizás podría detectar el idioma del usuario desde javascript http://stackoverflow.com/a/8199791 y entonces pedir vía ajax el fichero adecuado. Todo esto si no tienes lenguaje de programación de servidor (que la verdad es que para casos como estos ayuda bastante).

    ResponderEliminar
  24. Grande el trabajo, justo lo que andaba buscando gracias por la info! Saludos...

    ResponderEliminar
  25. Excelente ayuda, después de haber buscado y probado durante unas cinco horas, como validar que no ingresen un carácter especifico, por fin encontré lo que buscaba.

    Mil gracias.

    ResponderEliminar
  26. Hola necesito ayuda con este plugin, yo lo he utilizado otras veces con éxito pero ahora quiero utilizarlo para validar los diferentes pasos de un wizard sin enviar el formulario hasta el ultimo paso. Lleva varios días en eso y no he podido.
    Muchas gracias de antemano.

    ResponderEliminar
  27. Oies amigo es muy bueno y facil de entender tu explicacion, yo me preguntaba si existe alguna forma con este pluggin donde nos muestre un mensaje que diga solo se permiten letras(Sin numeros), espero me respondas o alguien que tenga una solucion gracias

    ResponderEliminar
    Respuestas
    1. holaa!! yo probe con esto y me funciono ok!

      VALIDAR TEXTBOX SOLOLETRAS


      function SoloLetras(evt) {
      var charCode = (evt.which) ? evt.which : event.keyCode
      if (charCode > 31 && (charCode < 48 || charCode > 57))
      return true;
      return false;
      }


      ------- ASP.NET CONTROL TEXTBOX cargo


      Eliminar
    2. Este comentario ha sido eliminado por el autor.

      Eliminar

    3. function SoloLetras(evt) {
      var charCode = (evt.which) ? evt.which : event.keyCode
      if (charCode > 31 && (charCode < 48 || charCode > 57))
      return true;
      return false;
      }

      ------- ASP.NET CONTROL TEXTBOX cargo

      Eliminar
    4. holaa!! yo probe con esto y me funciono ok!

      VALIDAR TEXTBOX SOLOLETRAS


      function SoloLetras(evt) {
      var charCode = (evt.which) ? evt.which : event.keyCode
      if (charCode > 31 && (charCode < 48 || charCode > 57))
      return true;
      return false;
      }


      ------- ASP.NET CONTROL TEXTBOX cargo


      Eliminar
  28. seria genial si se pudiera descargar el proyecto y verlo funcionar en directo u.u

    ResponderEliminar
  29. seria genial si se pudiera descargar el proyecto y verlo funcionar en directo u.u

    ResponderEliminar
  30. Como puedo validar un campo que no se pase de los 10000.00 pesos..??
    ayuda..!!!

    ResponderEliminar
  31. Como puedo validar un campo que no se pase de los 10000.00 pesos..??
    ayuda..!!!

    ResponderEliminar
  32. Excelente aporte, muchas gracias!!! :)

    ResponderEliminar
  33. Gracias amigo, a pesar de los años que han pasado esto sigue vigente!!!

    ResponderEliminar