Enviar formularios con AJAX y jQuery

En nuestro tutorial rápido de jQuery ya explicamos cómo enviar peticiones HTTP asíncronas al servidor utilizando distintos métodos de esta librería, como $.load, $.get, $.post y $.getJSON. En esta ocasión, y a petición de varios lectores, utilizaremos un pequeño ejemplo para ver cómo enviar los datos de un formulario utilizando AJAX y jQuery, y cómo hacer uso de estos datos en un archivo PHP situado en nuestro servidor.

Comencemos por el formulario. Nuestra pequeña aplicación de ejemplo no hará más que tomar dos números y sumarlos en el servidor. No es nada que no pudiéramos hacer en la parte de cliente usando JavaScript, por lo que no es un ejemplo muy espectacular, pero sí instructivo. Necesitaremos 2 cajas de texto y un botón de enviar. Tendremos también una etiqueta <p> bajo el formulario, que será donde se muestre el resultado.

<html>
<body>
<form action="sumar.php">
  <input type="text" name="num1" /> + <input type="text" name="num2" /><br/>
  <input type="submit" value="Sumar" />
</form>
<p id="resultado"></p>
</body>
</html>

Vayamos ahora con el código JavaScript que enviará el formulario y actualizará la página con el resultado. Una vez añadido este código, este sería el aspecto de la página:

<html>
<body>
<form action="sumar.php" id="formularioSuma">
  <input type="text" name="num1" /> + <input type="text" name="num2" /><br/>
  <input type="submit" value="Sumar" />
</form>
<p id="resultado"></p>

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

<script type="text/javascript">
$('#formularioSuma').submit(function(event) {
  event.preventDefault();
  var url = $(this).attr('action');
  var datos = $(this).serialize();
  $.get(url, datos, function(resultado) {
    $('#resultado').html(resultado);
  });
});
</script>
</body>
</html>

Como vemos, lo que hace este código es establecer una función a utilizar como manejador para el evento submit del formulario, evento que se produce al intentar enviarlo.

Esta función se encarga de bloquear el comportamiento por defecto con event.preventDefault(), de forma que el formulario no se envíe de forma síncrona; obtener la URL a la que enviar el formulario de su atributo action, serializar los datos del formulario para enviarlos en la petición con serialize() y, por último, enviar estos datos utilizando una petición GET, mediante el método del mismo nombre.

El tercer argumento de get es, como recordaréis, una función de callback que será llamada cuando termine de ejecutarse la petición. En nuestro caso, esta función no hará más que sustituir el contenido de la etiqueta <p> con el resultado devuelto por la página PHP, ya sea este un error o la suma de ambos números.

Si imprimimos la variable datos veremos que es una simple cadena con los datos codificados como si se tratara de parámetros en una URL. Si fuéramos a sumar 10 y 20, por ejemplo, su aspecto sería:

num1=2&num2=2

jQuery es lo bastante inteligente para añadir esta cadena a la URL en caso de que se trate de una petición GET, por lo que el resultado sería algo como http://servidor.com/sumar.php?num1=10&num2=20 o dentro de la petición si se envía por POST. El acceso a estos datos en el archivo PHP, por tanto, es de lo más sencillo; sólo tenemos que utilizar las matrices superglobales $_GET y $_POST para acceder directamente a los valores.

<?php
if(is_numeric($_GET['num1']) and is_numeric($_GET['num2']))
  echo $_GET['num1'] + $_GET['num2'];
else
  echo 'Los operandos no son correctos';

Otra opción, a parte de serialize, habría sido utilizar el método serializeArray. Mientras que el primero genera una cadena con los parámetros codificados como si de una URL se tratase, como ya comentamos, la segunda produciría un array de objetos. No obstante, el acceso a los datos en el archivo PHP sería exactamente igual en ambos casos, ya que jQuery se encargaría de procesar el array.


31 comentarios en «Enviar formularios con AJAX y jQuery»

  1. En el tutorial de jQuery ya expliqué un poco cómo trabajar con JSON, pero ya veremos en algún próximo artículo algún otro ejemplo, para casos en que los datos que tengamos que intercambiar entre cliente y servidor sean más complejos.

  2. Muchas gracias por la información;
    No sabía de la función event.preventDefault(); , y me volvía loco para intentar por todos los medios que no enviase el formulario hasta que estuvieran las funciones de validación/procesamiento pasadas.

    Saludos 🙂

  3. Pingback: Procesar peticiones php con jQuery | UnUsuario

  4. Magnifico… son estas entradas las que me hacen volver a Mundo Geek prácticamente todos los días.

    Mi trabajo con Ajax ha sido muy poco, pero me gustaría saber como hace por ejemplo Google para mientras se va escribiendo muestre los resultados en el cuadro de texto? Supongo será con un evento onChange y mandando esa información al servidor no.

    Junto con los enlaces de sitio me parecen opciones muy interesantes… razón por la que utilizo ese buscador y no Bing o Yahoo.

    Un saludo!

    1. Pues sí, usualmente se hace con los eventos ‘onchange’ y ‘onkeyup’ de Javascript. Yo he hecho pequeñas aplicaciones AJAX dentro de webs más completas, tales como buscadores de productos, sistemas de envío y votación, etc… y la verdad es que se aprende mucho en el proceso.

      Personalmente prefiero utilizar Javascript «a pelo», sin la ayuda de bibliotecas como Jquery o Prototype, que si bien es verdad que facilitan bastante el trabajo y hacen el código más breve y elegante, pueden no ser el mejor método para implementar AJAX si lo que te interesa realmente es aprender.

      Por cierto, me gustaría compartir con todos un modo de iniciar el objecto XMLHttpRequest() de JS independientemente del navegador en el que se esté ejecutando. Yo utilizo una variable del siguiente tipo (de cosecha propia):

      var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false;

      Los condicionales ternarios pueden ser muy utiles. 🙂

      1. Gracias @[DoodoM], por cierto, tiene sitio web o blog?

        Seria interesante que compartiera esas aplicaciones, si quiere por mi blog o por aquí si se puede…

        En cuanto a lo de jQuery, pues yo había visto que hacían lo mismo pero sin utilizarlo creando un archivo buscar.js y mostrando los resultados en una capa, aunque claro, ya todos sabemos las ventajas de usar un Framework.

        Pues a mi me interesa es aprender, pero utilizando jQuery mato dos pajaros de un solo tiro xD

        Saludos!

      2. Si compartiera alguna de mis creaciones de un modo directo o indirecto, enlazando o no a la página web en las que la implementé, mi identidad virtual quedaría con el culo al descubierto (si no lo está ya gracias al amigo Google).

        De modo que no te lo tomes como algo personal si decido no hacer público nada por aquí. Si creo conveniente publicar algo que haya aprendido o realizado, lo haré en mi actual blog: http://sysd.es

        Un saludo. 😉

  5. Pingback: links for 2010-05-10 | RGBitmap – Diseño, Desarrollo y Creatividad + TICs

  6. el codigo es excelente, aunq e probado usar con post, tratando a un link de submit, se podría hacer un link de submit pero en un formulario con method post???

  7. Hola,

    Habría alguna diferencia entre el event.preventDefault(); y poner un return false en el propio formulario?

    Un saludo hamijos!

  8. Es importante recordar que la función de event.preventdefault debe aparecer DESPUES de la impresión del formulario, sino no anda. Estuve horas probando hasta que me dí cuenta 🙁

    Saludos y muchas gracias !

  9. hola, excelente aportacion pero tengo una duda,

    si en vez de submit tienes esto:

    no funciona el .submit

    me preguntaba como podria hacer para q funcionase teniendo la estructura q yo tengo ya q sino tendria q modificar toda la web q estoy creando y soy nuevo con esto de jquery y ajax y no tengo mucha idea

    muchas gracias de antemano

  10. Pingback: DIARIO DEL PROGRAMADOR

  11. Tiene un error cuando usas
    digamos que si quieres guardar los valores en un php
    lo hace a la primera correctamente,pero despues cuando modifiques y des guardar otra vez no lo hara
    hasta que le des en la tercera vez entonces lo hara pero esto genera una cadenita, digamos
    1 lo guarda
    2 no lo guarda pero lo almacena
    3 lo almacena pero cuando deberia guardar 3 guarda 2.
    var datos = $(this).serialize();
    he notado que el serialize no actualiza :s. alguien teine alguna solucion?

  12. hola que tal… veo temas muy importates y de gran utilida en eta pagina,, quiero aprender mucho y lo mejor es poninedo tod en practica, tengo un inconveniete con un propuesta a resolver
    el tema es el siguiente:
    necesito realizar las sentencias CRUD, con ajax usando el framework jquery, lo raro es q me piden manipulando el DOM… alguna idea??? Graxias!!!

    1. usa el Firebug de Firefox para revisar el DOM de tu pagina actual y a partir de ahi puedes usarel DOM para usar esos valores
      un saludo

  13. Saludos!

    Probé los scripts y trabajaron bien… yo estoy enfrascado en un dilema que gira en la obtención de valores con jquery y trasladarlos a un script en php. Haber si alguien me puede ayudar con lo siguiente.

    Uno de los componentes del formulario es de la siguiente manera ¡:

    Características del Dormitorio:

    Individual
    Doble
    Triple
    Cuadruple
    Jr Suite
    Suite

    Sencilla
    Doble
    Queen Size
    King Size
    Sofá cama

    Si
    No

    Si tiene baño
    No tiene baño

    Walk-in Closet
    Closet normal
    No tiene closet

    Cantidad:

    @@@@@@@@@@@@@@@@@@@@@@

    Como verán, es un select multiple con optgoup que, de necesitarse, se puede generan un select similar dinamicamente con este script en jquery co lo encontré por … por… bueno… no se donde y lo cambie un poquillo para que se adapte a lo que se necesita… aquí esta el script jquery:

    $(document).ready(function() {
    //ACA le asigno el evento click a cada boton de la clase bt_plus y llamo a la funcion addField
    $(«.bt_plus»).each(function (e){
    $(this).bind(«click»,addField);
    });
    });

    function addField(){
    // ID del elemento div quitandole la palabra «div_» de delante. Pasi asi poder aumentar el número. Esta parte no es necesaria pero yo la utilizaba ya que cada campo de mi formulario tenia un autosuggest , así que dejo como seria por si a alguien le hace falta.

    var clickID = parseInt($(this).parent(‘div’).attr(‘id’).replace(‘div_’,»));

    // Genero el nuevo numero id
    var newID = (clickID+1);

    // Creo un clon del elemento div que contiene los campos de texto
    $newClone = $(‘#div_’+clickID).clone(true);

    //Le asigno el nuevo numero id
    $newClone.attr(«id»,’div_’+newID);

    $newClone.children(«#dormitorios option::selected»).remove();
    $newClone.children(«#dormitorios»).attr(«name»,»dormitorios[«+ newID +»]»);

    //Borro el valor del segundo campo input(este caso es el campo de cantidad) y lo identifico secuencialmente
    $newClone.children(«input»).eq(0).val(»);
    $newClone.children(«#cantdorm»).attr(«name»,»cantdorm[«+ newID +»]»);
    //Asigno nuevo id al boton
    $newClone.children(«input»).eq(1).attr(«id»,newID)

    //Inserto el div clonado y modificado despues del div original
    $newClone.insertAfter($(‘#div_’+clickID));

    //Cambio el signo «+» por el signo «-» y le quito el evento addfield
    $(«#»+clickID).val(‘-‘).unbind(«click»,addField);

    //Ahora le asigno el evento delRow para que borre la fial en caso de hacer click
    $(«#»+clickID).bind(«click»,delRow);

    }

    function delRow() {
    // Funcion que destruye el elemento actual una vez echo el click
    $(this).parent(‘div’).remove();

    }

    se algo de php y neófito en jquery.. lo que se ha hecho hasta este momento ha sido a punta de algunos ejemples, probar, errar y asi…

    la recepción de datos en php solo me muestra las selecciones que se realizan en el select padre… pero los hijos… esos hijos de…p… jajaja no aparecen por ningún lado! si alguien puede tener la amabilidad de desasnarme, le quedo desde ya muy agradecido..

  14. lo siento el formulario se transcribio mal… aqui la corrección:

    <form method="post" name="form">
    <div id="div_1">
    <strong>Características del Dormitorio:</strong>
    <select name="dormitorios[]" size="4" multiple="multiple" class="text, required" id="dormitorios" >
    <optgroup label="Tipo">
    <option value="Individual"><strong>Individual</strong></option>
    <option value="Doble"><strong>Doble</strong></option>
    <option value="Triple"><strong>Triple</strong></option>
    <option value="Cuadruple"><strong>Cuadruple</strong></option>
    <option value="Jr Suite"><strong>Jr Suite</strong></option>
    <option value="Suite"><strong>Suite</strong></option>
    </optgroup>
    <optgroup label="Camas">
    <option value="Sencilla"><strong>Sencilla</strong></option>
    <option value="Doble"><strong>Doble</strong></option>
    <option value="Queen size"><strong>Queen Size</strong></option>
    <option value="King size"><strong>King Size</strong></option>
    <option value="Sof&aacute; cama"><strong>Sof&aacute; cama</strong></option>
    </optgroup>
    <optgroup label="Cama Supletoria">
    <option value="Si"><strong>Si</strong></option>
    <option value="No"><strong>No</strong></option>
    </optgroup>
    <optgroup label="Ba&ntilde;o">
    <option value="Si tiene Ba&ntilde;o"><strong>Si tiene baño</strong></option>
    <option value="No tiene ba&ntilde;o"><strong>No tiene baño</strong></option>
    </optgroup>
    <optgroup label="Closet">
    <option value="Walk-in Closet"><strong>Walk-in Closet</strong></option>
    <option value="Closet normal"><strong>Closet normal</strong></option>
    <option value="No tiene closet"><strong>No tiene closet</strong></option>
    </optgroup>
    </select>

    <strong> Cantidad: </strong>
    <input id="cantdorm" name="cantdorm[]" type="text" class="input, required" style="width:40px;" />
    <input name="button" type="button" class="bt_plus" id="1" value="+" title="Puede crear más casilleros de caracteristicas de acuerdo al numero de dormitorios que desea ingresar" />
    </div>
     
    <p>
    <input type="submit" name="s1" value="Enviar">
    </p>
    </form>

  15. Tengo un problema, necesito que un formulario envie los parametros con el formato /controller/action/city:buenos aires/poblacion:100000

    o sea las variables las necesito en el formato variable:valor

    Pero cuando envio el form por url lo hace de la forma clasica ?variable=valor

    Como puedo hacer?

  16. Aprovechando el ejemplo, que por cierto es muy ilustrativo. ¿ A que se debe que la url destino, en este caso sumar.php dé error y muestre el mensaje del else, siendo la petición ajax jquery exitosa.?
    El ejemplo lo probé usando wampserver v2.2.

  17. probe tu codigo y me redirecciona a la pagina a la que llamo (donde proceso el formulario), sabes que pueda ser?, no le cambie nada a tu codigo solo le puse mi archivo y mis campos

Responder a Martin Cancelar respuesta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.