feb 10 2008

Validación Ajax mediante serialización del formulario

Published by at 11:12 pm under Programación

Estos últimos días he estado probando una nueva forma de validar formularios que me ha convencido bastante, se trata de serializar los datos del formulario en JavaScript y enviarlos a través de una conexión XHR(XmlHttpRequest) al servidor, este sería el funcionamiento,

  1. El usuario rellena todos los campos del formulario y pulsa el botón de enviar.
  2. Al dispararse el evento onsubmit serializamos los campos del formulario y realizamos una petición XHR al servidor para que realice la validación.
  3. El servidor realiza la validación y devuelve en formato JSON el resultado con el nombre de los campos erróneos y los mensajes a visualizar.
  4. El cliente recupera el resultado.
    - Si hay algún error se muestra por pantalla mediante HTML dinámico.
    - Si no hay errores se envía el formulario a través de submit.
  5. El servidor realiza una segunda validación de los datos.
    - Si hay errores se vuelve a recargar el formulario presentándolos.
    - Si no hay errores, continúa con el proceso de guardado y siguientes acciones.
    Esta segunda validación es importante ya que el usuario puede tener un navegador que no soporte javascript o haberlo deshabilitado para saltarse la validación Ajax.

Principales ventajas:

  • Accesibilidad. La petición Ajax se realiza en el evento onsubmit del formulario, por lo que si el usuario no tiene javascript seguirá funcionando correctamente.
  • Al realizarse por Ajax la primera validación de los datos no es necesario recargar la página
  • Evitamos desarrollar por duplicado la validación en javascript y por otro lado la validación en el servidor.
  • Permite tanto la validación del formulario completo una vez se pulsa submit como la validación campo por campo a través de eventos onchange/onblur de cada campo.
  • Permite realizar comprobaciones avanzadas que requieran acceso a base de datos.
  • Al contrario que las soluciones basadas en iframes, mediante XHR no cambia el estado del history.

Inconvenientes:

  • Es un poco más lento que realizar la validación en javascript.
  • La mayor parte de los controles como cajas de texto, selects, radios… funcionan bien, aunque los input type=submit, image y reset no se envían correctamente. Siempre que se sepa no debería ser un problema. Existe una comparativa con las diferencias en la serialización que realizan diferentes librerías como jquery, dojo, prototype, YUI y Moochkit en JavaScript Form Serialization Comparison.

Pongo un ejemplo con parte de la implementación en PHP y la la libreria de JavaScript YUI

Devolución en formato JSON del resultado de la validación desde el servidor:

$errores=array();
$errores[]=array('TIPO'  => 'ERROR',
                 'TEXTO'   => 'El login debe tener un mínimo de 6 letras',
                 'CAMPO' => 'login',
                 );
if (count($errores)>0){
 	Zend_Loader::loadClass('Zend_Json');
        echo Zend_Json::encode($errores);
} else {
         echo 'false';
}

Serialización del formulario, petición ajax y presentación de los mensajes:

var $=YAHOO.util.Dom.get;
validaciones = {
    handleSuccess:function(o){
        if(o.responseText !== undefined){
        var res = eval("(" + o.responseText + ")");
        if (!res){
            document.forms['formulario'].submit();
        } else {
            $('divErrores').innerHTML='';
            for (var i=0;i<res.length;i++){
                if(res[i]['TIPO']=='ERROR'){
                    var str='<div class="error">'+res[i]['TEXTO']+'</div>';
                    $('divErrores').innerHTML=$('divErrores').innerHTML+str;
                }
            }
            $(res[0]['CAMPO']).focus();
        }
    }    },
    handleFailure:function(o){
        if(o.responseText !== undefined){
            var str='Se produjo un error al realizar la conexión<br />';
            $('divErrores').innerHTML=$('divErrores').innerHTML+str;
        }
    },
    enviar:function() {
        YAHOO.util.Connect.setForm($('formulario'));
        var sUrl = "/index.php/modulo/validar/";
 	var callback =
        {
            success:validaciones.handleSuccess,
            failure:validaciones.handleFailure,
            scope: validaciones
        };
 	var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback);
        return false;
    }
};

Div para presentar los errores y formulario HTML:

<span id='divErrores'></span>
<form name='formulario' id='formulario' action="/index.php/modulo/envioFormulario/"
method="post" onsubmit="return validaciones.enviar();">        

<input type="text" value="" name='login' id='login' />
 ...

<input type='submit' name='enviar' value='Enviar' />
</form>

No responses yet

Trackback URI | Comments RSS

Leave a Reply