Formulario de envío de jQuery AJAX

939

Tengo un formulario con nombre orderproductForm y un número indefinido de entradas.

Quiero hacer algún tipo de jQuery.get o ajax o algo así que llame a una página a través de Ajax y envíe todas las entradas del formulario orderproductForm .

Supongo que una forma sería hacer algo como

jQuery.get("myurl",
          {action : document.orderproductForm.action.value,
           cartproductid : document.orderproductForm.cartproductid.value,
           productid : document.orderproductForm.productid.value,
           ...

Sin embargo, no sé exactamente todas las entradas de formulario. ¿Hay una característica, función o algo que simplemente envíe TODAS las entradas del formulario?

Nathan H
fuente

Respuestas:

814

Puede usar las funciones ajaxForm / ajaxSubmit del complemento de formulario Ajax o la función jQuery serialize.

AjaxForm :

$("#theForm").ajaxForm({url: 'server.php', type: 'post'})

o

$("#theForm").ajaxSubmit({url: 'server.php', type: 'post'})

ajaxForm enviará cuando se presione el botón enviar. ajaxSubmit envía de inmediato.

Serializar :

$.get('server.php?' + $('#theForm').serialize())

$.post('server.php', $('#theForm').serialize())

La documentación de serialización de AJAX está aquí .

jspcal
fuente
2
idea interesante, sin embargo, no controlo el lado del servidor al que llamo, por lo tanto, no puedo enviarle datos serializados
Nathan H
25
Sí, puede, el nombre no es importante, lo que hará es enviar pares de cada clave de formulario y cada variable de formulario.
66
Se serializa en una cadena de consulta, al igual que los datos que está poniendo en la matriz manualmente en la llamada GET que habría. Esto es lo que quieres, estoy bastante seguro.
JAL
1
oooh ya veo, luego agrego esta cadena al final de la URL en la llamada get. Estaba pensando en PHP serializar. Lo siento. ¡Gracias!
Nathan H
238
.ajaxSubmit()/ .ajaxForm()no son funciones básicas de jQuery: necesita el complemento de formulario jQuery
Yarin
1401

Esta es una referencia simple:

// this is the id of the form
$("#idForm").submit(function(e) {

    e.preventDefault(); // avoid to execute the actual submit of the form.

    var form = $(this);
    var url = form.attr('action');

    $.ajax({
           type: "POST",
           url: url,
           data: form.serialize(), // serializes the form's elements.
           success: function(data)
           {
               alert(data); // show response from the php script.
           }
         });


});

Espero que te ayude.

Alfrekjv
fuente
46
Pero form.serialize () no puede publicar <input type = "file"> en IE
macio.Jun
2
¡Gran respuesta para el envío normal de formularios!
The Sheek Geek
1
Similar a @ BjørnBørresen, también puede usarlo type: $(this).attr('method')si usa el methodatributo en su formulario.
djule5
2
Vale la pena mencionar que desde jQuery 1.8, .success, .error y .complete están en desuso a favor de .done, .fail y .always.
Adam
2
Comentario de @ JohnKary: gran artículo, parece que ya no está disponible. Aquí hay un archivo de eventos jQuery: Stop (Mis) Using Return False
KyleMit
455

Otra solución similar que utiliza atributos definidos en el elemento de formulario:

<form id="contactForm1" action="/your_url" method="post">
    <!-- Form input fields here (do not forget your name attributes). -->
</form>

<script type="text/javascript">
    var frm = $('#contactForm1');

    frm.submit(function (e) {

        e.preventDefault();

        $.ajax({
            type: frm.attr('method'),
            url: frm.attr('action'),
            data: frm.serialize(),
            success: function (data) {
                console.log('Submission was successful.');
                console.log(data);
            },
            error: function (data) {
                console.log('An error occurred.');
                console.log(data);
            },
        });
    });
</script>
Davide Icardi
fuente
¿Alguna sugerencia sobre cómo hacer esto si el atributo de nombre incluye un "."? (Requisito del lado del servidor, no es mi idea).
Josef Engelfrost
Incluya una devolución de llamada de error a esto para completarlo. Uno nunca sabe cuándo recibirá un error, siempre debe tenerlo en cuenta.
codificación de Aaron
1
Si no establece el método o la acción, se configuran por defecto gety la URL actual, respectivamente. Podría hacer con agregar esta suposición al código.
rybo111
1
Según la documentación de jQuery ( api.jquery.com/submit ), frm.submit (function (event) {..}); es equivalente a frm.on ("submit", function (event) {..}) ;. Para mí, esto último es más legible, ya que es obvio que está adjuntando un controlador de eventos a un elemento que se ejecutará cuando se active el evento.
mehmet
177

Hay algunas cosas que debes tener en cuenta.

1. Hay varias formas de enviar un formulario

  • usando el botón de enviar
  • presionando enter
  • activando un evento de envío en JavaScript
  • posiblemente más dependiendo del dispositivo o dispositivo futuro.

Por lo tanto, debemos vincularnos al evento de envío del formulario , no al evento de clic del botón. Esto garantizará que nuestro código funcione en todos los dispositivos y tecnologías de asistencia ahora y en el futuro.

2. Hijax

Es posible que el usuario no tenga habilitado JavaScript. Un patrón de hijax es bueno aquí, donde tomamos suavemente el control del formulario usando JavaScript, pero lo dejamos enviable si JavaScript falla.

Deberíamos extraer la URL y el método del formulario, por lo que si el HTML cambia, no necesitamos actualizar el JavaScript.

3. JavaScript discreto

Usar event.preventDefault () en lugar de return false es una buena práctica, ya que permite que el evento burbujee. Esto permite que otros scripts se vinculen con el evento, por ejemplo, scripts de análisis que pueden estar monitoreando las interacciones del usuario.

Velocidad

Idealmente deberíamos usar un script externo, en lugar de insertar nuestro script en línea. Podemos vincularnos a esto en la sección de encabezado de la página usando una etiqueta de script, o vincularlo en la parte inferior de la página para mayor velocidad. El script debería mejorar silenciosamente la experiencia del usuario, no interferir.

Código

Suponiendo que está de acuerdo con todo lo anterior, y desea capturar el evento de envío y manejarlo a través de AJAX (un patrón hijax), podría hacer algo como esto:

$(function() {
  $('form.my_form').submit(function(event) {
    event.preventDefault(); // Prevent the form from submitting via the browser
    var form = $(this);
    $.ajax({
      type: form.attr('method'),
      url: form.attr('action'),
      data: form.serialize()
    }).done(function(data) {
      // Optionally alert the user of success here...
    }).fail(function(data) {
      // Optionally alert the user of an error here...
    });
  });
});

Puede activar manualmente el envío de un formulario cuando lo desee a través de JavaScript utilizando algo como:

$(function() {
  $('form.my_form').trigger('submit');
});

Editar:

Recientemente tuve que hacer esto y terminé escribiendo un complemento.

(function($) {
  $.fn.autosubmit = function() {
    this.submit(function(event) {
      event.preventDefault();
      var form = $(this);
      $.ajax({
        type: form.attr('method'),
        url: form.attr('action'),
        data: form.serialize()
      }).done(function(data) {
        // Optionally alert the user of success here...
      }).fail(function(data) {
        // Optionally alert the user of an error here...
      });
    });
    return this;
  }
})(jQuery)

Agregue un atributo data-autosubmit a su etiqueta de formulario y luego puede hacer esto:

HTML

<form action="/blah" method="post" data-autosubmit>
  <!-- Form goes here -->
</form>

JS

$(function() {
  $('form[data-autosubmit]').autosubmit();
});
superluminario
fuente
2
¿Cómo puedo agregar las devoluciones de llamada a las funciones 'hecho' y 'fallar'? algo así como $ ('form [data-autosubmit]'). autosubmit (). done (function ({...}); Esto es posible?
Crusader
1
Hola @Crusader: ciertamente, en lugar de que este complemento devuelva esto, podrías hacer que devuelva el evento ajax, luego podrías encadenarlo directamente. Alternativamente, puede hacer que el complemento reciba una devolución de llamada exitosa.
superluminary
No veo cómo sucede esto "... déjalo enviable si JavaScript falla".
mehmet
@mmatt: si JavaScript está deshabilitado, el formulario sigue siendo solo un formulario. El usuario hace clic en enviar y se produce un envío de formulario basado en el navegador normal. Llamamos a esto mejora progresiva. No es tan importante hoy en día, ya que los lectores de pantalla modernos admiten JavaScript.
superluminario
@mmatt: las devoluciones de llamada de promesa recibirán opcionalmente un parámetro que contiene los datos.
superluminario
41

También puede usar FormData (pero no disponible en IE):

var formData = new FormData(document.getElementsByName('yourForm')[0]);// yourForm: form selector        
$.ajax({
    type: "POST",
    url: "yourURL",// where you wanna post
    data: formData,
    processData: false,
    contentType: false,
    error: function(jqXHR, textStatus, errorMessage) {
        console.log(errorMessage); // Optional
    },
    success: function(data) {console.log(data)} 
});

Así es como usas FormData .

macio.Jun
fuente
8
Veo que FormData ahora es compatible con IE10. En unos pocos años, esta será la solución preferida.
superluminario
3
¿Qué ventaja de esta manera?
insign
1
La ventaja de @insign es que no se requiere ningún complemento y funciona en muchos navegadores modernos.
KhoPhi
44
@insign FormData también puede manejar archivos (si hay uno de esos campos en su formulario) mientras que serialize () simplemente lo ignora.
mehmet
TypeError no capturado: Error al construir 'FormData': el parámetro 1 no es del tipo 'HTMLFormElement'
rahim.nagori
28

Versión simple (no envía imágenes)

<form action="/my/ajax/url" class="my-form">
...
</form>
<script>
    (function($){
        $("body").on("submit", ".my-form", function(e){
            e.preventDefault();
            var form = $(e.target);
            $.post( form.attr("action"), form.serialize(), function(res){
                console.log(res);
            });
        });
    )(jQuery);
</script>

Copiar y pegar una modificación de un formulario o todos los formularios en una página

Es una versión modificada de la respuesta de Alfrekjv.

  • Funcionará con jQuery> = 1.3.2
  • Puede ejecutar esto antes de que el documento esté listo
  • Puede eliminar y volver a agregar el formulario y aún funcionará
  • Se publicará en la misma ubicación que el formulario normal, especificado en el atributo "action" del formulario

JavaScript

jQuery(document).submit(function(e){
    var form = jQuery(e.target);
    if(form.is("#form-id")){ // check if this is the form that you want (delete this check to apply this to all forms)
        e.preventDefault();
        jQuery.ajax({
            type: "POST",
            url: form.attr("action"), 
            data: form.serialize(), // serializes the form's elements.
            success: function(data) {
                console.log(data); // show response from the php script. (use the developer toolbar console, firefox firebug or chrome inspector console)
            }
        });
    }
});

Quería editar la respuesta de Alfrekjv, pero me desviaba demasiado de ella, así que decidí publicar esto como una respuesta separada.

No envía archivos, no admite botones, por ejemplo, al hacer clic en un botón (incluido un botón de envío) se envía su valor como datos de formulario, pero como se trata de una solicitud ajax, no se enviará el clic del botón.

Para admitir botones, puede capturar el clic real del botón en lugar del envío.

jQuery(document).click(function(e){
    var self = jQuery(e.target);
    if(self.is("#form-id input[type=submit], #form-id input[type=button], #form-id button")){
        e.preventDefault();
        var form = self.closest('form'), formdata = form.serialize();
        //add the clicked button to the form data
        if(self.attr('name')){
            formdata += (formdata!=='')? '&':'';
            formdata += self.attr('name') + '=' + ((self.is('button'))? self.html(): self.val());
        }
        jQuery.ajax({
            type: "POST",
            url: form.attr("action"), 
            data: formdata, 
            success: function(data) {
                console.log(data);
            }
        });
    }
});

En el lado del servidor, puede detectar una solicitud ajax con este encabezado que jquery estableceHTTP_X_REQUESTED_WITH para php

PHP

if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    //is ajax
}
Timo Huovinen
fuente
¿Cómo funcionaría esto si quisieras enviar un archivo con este formulario?
Yami Medina
1
@YamiMedina no es una solución simple, debe enviar toda la solicitud en un formato diferente (formato de varias partes) con los datos del archivo
Timo Huovinen
22

Este código funciona incluso con entrada de archivo

$(document).on("submit", "form", function(event)
{
    event.preventDefault();        
    $.ajax({
        url: $(this).attr("action"),
        type: $(this).attr("method"),
        dataType: "JSON",
        data: new FormData(this),
        processData: false,
        contentType: false,
        success: function (data, status)
        {

        },
        error: function (xhr, desc, err)
        {


        }
    });        
});
Shaiful Islam
fuente
3
Solo para notar que formData () es IE10 + developer.mozilla.org/en-US/docs/Web/API/FormData
Chris Hopkins
1
el tipo de datos: 'json' es importante si desea utilizar form.serialize ()
David Morrow
wow, este FormData es maravilloso! en caso de que alguien necesite: Array.from(new FormData(form))itera sobre este iterador de formdata :)
test30
13

Realmente me gustó esta respuesta de superluminary y especialmente la forma en que envolvió la solución en un complemento jQuery . Así que gracias a superluminary por una respuesta muy útil. Sin embargo, en mi caso, quería un complemento que me permitiera definir el éxito y el error controladores de eventos de por medio de opciones cuando se inicializa el complemento.

Así que aquí está lo que se me ocurrió:

;(function(defaults, $, undefined) {
    var getSubmitHandler = function(onsubmit, success, error) {
        return function(event) {
            if (typeof onsubmit === 'function') {
                onsubmit.call(this, event);
            }
            var form = $(this);
            $.ajax({
                type: form.attr('method'),
                url: form.attr('action'),
                data: form.serialize()
            }).done(function() {
                if (typeof success === 'function') {
                    success.apply(this, arguments);
                }
            }).fail(function() {
                if (typeof error === 'function') {
                    error.apply(this, arguments);
                }
            });
            event.preventDefault();
        };
    };
    $.fn.extend({
        // Usage:
        // jQuery(selector).ajaxForm({ 
        //                              onsubmit:function() {},
        //                              success:function() {}, 
        //                              error: function() {} 
        //                           });
        ajaxForm : function(options) {
            options = $.extend({}, defaults, options);
            return $(this).each(function() {
                $(this).submit(getSubmitHandler(options['onsubmit'], options['success'], options['error']));
            });
        }
    });
})({}, jQuery);

Este complemento me permite "ajaxificar" formularios html en la página y proporcionar controladores de eventos de envío , éxito y error para implementar comentarios al usuario sobre el estado del envío del formulario. Esto permitió que el complemento se usara de la siguiente manera:

 $('form').ajaxForm({
      onsubmit: function(event) {
          // User submitted the form
      },
      success: function(data, textStatus, jqXHR) {
          // The form was successfully submitted
      },
      error: function(jqXHR, textStatus, errorThrown) {
          // The submit action failed
      }
 });

Tenga en cuenta que el éxito y el error controladores de eventos de reciben los mismos argumentos que recibiría de los eventos correspondientes del método jQuery ajax .

BruceHill
fuente
9

Tengo lo siguiente para mí:

formSubmit('#login-form', '/api/user/login', '/members/');

dónde

function formSubmit(form, url, target) {
    $(form).submit(function(event) {
        $.post(url, $(form).serialize())
            .done(function(res) {
                if (res.success) {
                    window.location = target;
                }
                else {
                    alert(res.error);
                }
            })
            .fail(function(res) {
                alert("Server Error: " + res.status + " " + res.statusText);

            })
        event.preventDefault();
    });
}

Esto supone que la publicación en 'url' devuelve un ajax en forma de {success: false, error:'my Error to display'}

Puedes variar esto como quieras. Siéntase libre de usar ese fragmento.

Tarion
fuente
1
¿Qué hay targetpara aquí? ¿Por qué enviaría un formulario con AJAX, solo para redirigirlo a una nueva página?
1252748
9

El formulario de envío de jQuery AJAX no es más que enviar un formulario utilizando el ID del formulario cuando hace clic en un botón

Por favor siga los pasos

Paso 1: la etiqueta del formulario debe tener un campo ID

<form method="post" class="form-horizontal" action="test/user/add" id="submitForm">
.....
</form>

Botón en el que vas a hacer clic

<button>Save</button>

Paso 2: el evento de envío está en jQuery, lo que ayuda a enviar un formulario. en el siguiente código estamos preparando la solicitud JSON del nombre del elemento HTML .

$("#submitForm").submit(function(e) {
    e.preventDefault();
    var frm = $("#submitForm");
    var data = {};
    $.each(this, function(i, v){
        var input = $(v);
        data[input.attr("name")] = input.val();
        delete data["undefined"];
    });
    $.ajax({
        contentType:"application/json; charset=utf-8",
        type:frm.attr("method"),
        url:frm.attr("action"),
        dataType:'json',
        data:JSON.stringify(data),
        success:function(data) {
            alert(data.message);
        }
    });
});

para la demostración en vivo, haga clic en el siguiente enlace

¿Cómo enviar un formulario usando jQuery AJAX?

jeet singh parmar
fuente
5

Considere usar closest

$('table+table form').closest('tr').filter(':not(:last-child)').submit(function (ev, frm) {
        frm = $(ev.target).closest('form');
        $.ajax({
            type: frm.attr('method'),
            url: frm.attr('action'),
            data: frm.serialize(),
            success: function (data) {
                alert(data);
            }
        })
        ev.preventDefault();
    });
test30
fuente
5

Sé que esta es una jQuerypregunta relacionada, pero ahora los días con JS ES6 las cosas son mucho más fáciles. Como no hay una javascriptrespuesta pura , pensé que podría agregar una javascriptsolución pura simple a esto, que en mi opinión es mucho más limpia, utilizando la fetch()API. Esta es una forma moderna de implementar solicitudes de red. En su caso, dado que ya tiene un elemento de formulario, simplemente podemos usarlo para crear nuestra solicitud.

const form = document.forms["orderproductForm"];
const formInputs = form.getElementsByTagName("input"); 
let formData = new FormData(); 
for (let input of formInputs) {
    formData.append(input.name, input.value); 
}

fetch(form.action,
    {
        method: form.method,
        body: formData
    })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.log(error.message))
    .finally(() => console.log("Done"));
Alain Cruz
fuente
4

Para evitar múltiples envíos de datos:

No olvide desvincular el evento de envío, antes de que el formulario se envíe nuevamente, el usuario puede llamar a la función sumbit más de una vez, tal vez olvidó algo o fue un error de validación.

 $("#idForm").unbind().submit( function(e) {
  ....
Pavel Zheliba
fuente
4

Si está utilizando el formulario .serialize (), debe darle a cada elemento del formulario un nombre como este:

<input id="firstName" name="firstName" ...

Y el formulario se serializa así:

firstName=Chris&lastName=Halcrow ...
Chris Halcrow
fuente
4

Puede usar esto en la función de envío como a continuación.

Formulario HTML

<form class="form" action="" method="post">
    <input type="text" name="name" id="name" >
    <textarea name="text" id="message" placeholder="Write something to us"> </textarea>
    <input type="button" onclick="return formSubmit();" value="Send">
</form>

Función jQuery:

<script>
    function formSubmit(){
        var name = document.getElementById("name").value;
        var message = document.getElementById("message").value;
        var dataString = 'name='+ name + '&message=' + message;
        jQuery.ajax({
            url: "submit.php",
            data: dataString,
            type: "POST",
            success: function(data){
                $("#myForm").html(data);
            },
            error: function (){}
        });
    return true;
    }
</script>

Para obtener más detalles y una visita de muestra: http://www.spiderscode.com/simple-ajax-contact-form/

suresh raj
fuente
2

Esta no es la respuesta a la pregunta de OP,
pero en caso de que no pueda usar DOM de forma estática, también puede intentarlo de esta manera.

var $form = $('<form/>').append(
    $('<input/>', {name: 'username'}).val('John Doe'),
    $('<input/>', {name: 'user_id'}).val('john.1234')
);

$.ajax({
    url: 'api/user/search',
    type: 'POST',
    contentType: 'application/x-www-form-urlencoded',
    data: $form.serialize(),
    success: function(data, textStatus, jqXHR) {
        console.info(data);
    },
    error: function(jqXHR, textStatus, errorThrown) {
        var errorMessage = jqXHR.responseText;
        if (errorMessage.length > 0) {
            alert(errorMessage);
        }
    }
});
wonsuc
fuente
2

Tratar

fetch(form.action,{method:'post', body: new FormData(form)});

Kamil Kiełczewski
fuente
1

Solo un recordatorio amistoso que también datapuede ser un objeto:

$('form#foo').submit(function () {
    $.ajax({
        url: 'http://foo.bar/some-ajax-script',
        type: 'POST',
        dataType: 'json',
        data: {
            'foo': 'some-foo',
            'bar': 'some-bar'
        }
    }).always(function (data) {
        console.log(data);
    });

    return false;
});
Lucas Bustamante
fuente
1

JavaScript

(function ($) {
    var form= $('#add-form'),
      input = $('#exampleFormControlTextarea1');


   form.submit(function(event) {

       event.preventDefault(); 

       var req = $.ajax({
           url: form.attr('action'),
           type: 'POST',
           data: form.serialize()
       });
    req.done(function(data) {
       if (data === 'success') {
           var li = $('<li class="list-group-item">'+ input.val() +'</li>');
            li.hide()
                .appendTo('.list-group')
                .fadeIn();
            $('input[type="text"],textarea').val('');
        }
   });
});


}(jQuery));

HTML

    <ul class="list-group col-sm-6 float-left">
            <?php
            foreach ($data as $item) {
                echo '<li class="list-group-item">'.$item.'</li>';
            }
            ?>
        </ul>

        <form id="add-form" class="col-sm-6 float-right" action="_inc/add-new.php" method="post">
            <p class="form-group">
                <textarea class="form-control" name="message" id="exampleFormControlTextarea1" rows="3" placeholder="Is there something new?"></textarea>
            </p>
            <button type="submit" class="btn btn-danger">Add new item</button>
        </form>
Marty
fuente
-21

También está el evento submit, que se puede activar de esta manera $ ("# form_id"). Submit (). Usaría este método si el formulario ya está bien representado en HTML. Acabas de leer en la página, rellenar las entradas del formulario con cosas y luego llamar a .submit (). Utilizará el método y la acción definidos en la declaración del formulario, por lo que no necesita copiarlo en su JavaScript.

ejemplos

billw
fuente
58
Si elimina su publicación, obtendrá los puntos de penalización que le han sido devueltos.
sparkyspider
2
Esto enviará el formulario, pero no a través de AJAX, por lo que no responde la pregunta.
superluminario
11
lo que dijo @spider, además obtienes una bonita insignia llamada "presión de grupo"
nurettin