jquery serialize and $.post

69,553

Solution 1

If you are using a <button> element to activate the serialize and ajax, and if that <button> element is within the form element, the button automatically acts as a form submission, no matter what other .click assignment you give it with jQuery.

type='submit'

<button></button> and <button type='submit'></button> are the same thing. They will submit a form if placed within the <form> element.

type='button'

<button type='button'></button> is different. It is just a normal button and will not submit the form (unless you purposely make it submit the form via JavaScript).

And in the case where a form element has no action attribute specified, this submission simply sends the data back onto the same page. So you will end up seeing a page refresh, along with the serialized data appearing in the URL as if you used GET in your ajax.

Possible solutions

1 - Make the <button> type button. As explained above, this will prevent the button from submitting the form.

Before:

<form id='myForm'>
    <!--Some inputs, selects, textareas, etc here-->
    <button id='mySubmitButton'>Submit</button>
</form>

After:

<form id='myForm'>
    <!--Some inputs, selects, textareas, etc here-->
<button type='button' id='mySubmitButton'>Submit</button>
</form>

2 - Move the <button> element outside the <form> element. This will prevent the button from submitting the form.

Before:

<form id='myForm'>
    <!--Some inputs, selects, textareas, etc here-->
    <button id='mySubmitButton'>Submit</button>
</form>

After:

<form id='myForm'>
    <!--Some inputs, selects, textareas, etc here-->
</form>
<button id='mySubmitButton'>Submit</button>

3 - Add in the preventDefault() into the button click handler to prevent the form from being submitted (it's default action):

$("#addShowFormSubmit").click(function(event){
  event.preventDefault();
  var perfTimes = $("#addShowForm").serialize();
  $.post("includes/add_show.php", {name: $("#showTitle").val(), results: perfTimes },      function(data) {
    $("#addShowSuccess").empty().slideDown("slow").append(data);
  });
});

Obviously without seeing all your code, I have no idea if this is the case for your issue, but the only reason I have ever seen behavior you are describing is because the submit button was a <button> without a type specified.

Solution 2

try using serializeArray() instead of serialize(). serialize() will produce an url-encoded query string, whereas serializeArray() produces a JSON data structure.

Solution 3

What leads you to believe that the data is appended to the URL?

Anyway, wouldn't it make more sense to pass the form values in the form data itself? It will allow you to skip the "explode" step:

$("#addShowFormSubmit")
  .click(function() { 
      var perfTimes = $("#addShowForm").serialize(); 
      $.post("includes/add_show.php", 
         $.param({name: $("#showTitle").val()}) + "&" + perfTimes, 
         function(data) {...}); 
  });

Solution 4

So this is probably a bit obtuse, but I made a function to help me do this very thing since I got tired of making a bunch of fixes every time. serializeArray is kind of annoying because it provides a collection of objects, when all I wanted to have PhP reconstruct was an associative array. The function below will go through the serialized array and will build a new object with the appropriate properties only when a value exists.

Firstly, the function (it takes the ID of the form in question):

function wrapFormValues(form) { 
    form = "#" + form.attr("id") + " :input";
    form = $(form).serializeArray();
    var dataArray = new Object();

    for( index in form)
    {   
        if(form[index].value)   {
            dataArray[form[index].name] = form[index].value;    
        }
    }       

    return dataArray; 
}

When constructing my posts I also usually use an object since I usually tag on two or three other values before the form data and I think it looks cleaner than to define it inline, so the final step looks like this:

var payload = new Object(); 
//stringify requires json2.js from http://www.json.org/js.html
payload.data = JSON.stringify(data);

$.post("page.php", payload,  
    function(reply) {
        //deal with reply.
    });

Server-side all you have to do is $payload = json_decode($_POST['data'], true) and you have yourself an associative array where the keys are the names of your form fields.

Full disclaimer though, multiple-selects probably won't work here, you would probably only get whichever value was last on the list. This is also created very specifically to suit one of my projects, so you may want to tweak it to suit you. For instance, I use json for all of my replies from the server.

Share:
69,553

Related videos on Youtube

musoNic80
Author by

musoNic80

Updated on July 09, 2022

Comments

  • musoNic80
    musoNic80 almost 2 years

    I'm trying to send a lot of data from a form using the $.post method in jQuery. I've used the serialize() function first to make all the form data into one long string which I will then explode serverside. The weird thing is when I try and send it using $.post it appends the result of the serialize() to the URL as if I was sending it using GET. Anyone have any ideas why this is happening?

    Here's the jquery:

    $("#addShowFormSubmit").click(function(){
      var perfTimes = $("#addShowForm").serialize();
      $.post("includes/add_show.php", {name: $("#showTitle").val(), results: perfTimes }, function(data) {
        $("#addShowSuccess").empty().slideDown("slow").append(data);
      });
    });  
    

    here's the php:

    $show = $_POST['name'];
    $results = $_POST['results'];
    $perfs = explode("&", $results);
    foreach($perfs as $perf) {
        $perf_key_values = explode("=", $perf);
        $key = urldecode($perf_key_values[0]);
        $values = urldecode($perf_key_values[1]);
    }
    echo $key, $values;  
    
  • Sixten Otto
    Sixten Otto over 14 years
    Actually, the real trick is to, in your click handler, call the event's preventDefault() method. That will prevent the browser's native action from being performed.
  • lenkite
    lenkite almost 14 years
    Keep the button inside the form, but use the form's submit handler and return false $('#myForm').submit(function() {var data = this.serialize(); $.post(this.attr('action'), data, function() {alert('done!')}); return false});
  • angry kiwi
    angry kiwi about 13 years
    shouldn't it be "&" instead of & ?
  • Samson
    Samson over 11 years
    add type="button" to your <button> tag to avoid the form submission.