22

My $.ajax() is not serializing the button name and value.

I have a very simple form. It has a button and a textbox.

<form action="/MyController/MyAction" data-ajax-method="post" 
  data-ajax-mode="replace" data-ajax-target="#mypartial" id="myform" 
  method="post">
        <button type="submit" class="positive" name="button" value="click1">
            <img src="/Id/Images/Icons/16/enabled/tick.png" title="click1">
            Click
        </button>
        <input id="txtBlah" name="txtBlah" type="text" value="hello">
    </div>
</form>

When i call $(this).serialize(), the textbox is included in the string but not the button.

Debug.Log($(this).attr('id')); //== 'myform'
Debug.Log("data: " + $(this).serialize()); //== data: txtBlah=hello

I noted during research that with other questions the main reason was a missing name element on the button. I have a name element.

I have also tried making a very simple <input type="submit" name="mysubmit" /> which did not change anything.

solution i used

var buttonSubmit = (function (e)
{
    e.preventDefault();
    var form = $(this).closest('form');
    form.attr('data-button-name', $(this).attr('value'));
    form.closest('form').submit();
});
Valamas
  • 24,169
  • 25
  • 107
  • 177

4 Answers4

29

jQuery's serialize() is pretty explicit about NOT encoding buttons or submit inputs, because they aren't considered to be "successful controls". This is because the serialize() method has no way of knowing what button (if any!) was clicked.

I managed to get around the problem by catching the button click, serializing the form, and then tacking on the encoded name and value of the clicked button to the result.

$("button.positive").click(function (evt) {
    evt.preventDefault();

    var button = $(evt.target);                 
    var result = button.parents('form').serialize() 
        + '&' 
        + encodeURI(button.attr('name'))
        + '='
        + encodeURI(button.attr('value'))
    ;

    console.log(result);
});
slashingweapon
  • 11,007
  • 4
  • 31
  • 50
  • 1
    You can also just let the button click event bubble up to the form, and then use event.srcElement to figure out which button caused the submission. – slashingweapon Mar 26 '12 at 05:15
  • Thanks for you help. My solution was inspired by yours. I have updated my original question. – Valamas Mar 26 '12 at 06:18
5

Here's a catch-all solution that will look for an input in the button's containing form. If it exists, it'll set the value, otherwise it will create a hidden input and set its value. This can also be useful if you're not wanting to submit the form immediately.

$(document).on('click', '[name][value]:button', function(evt){
    var $button = $(evt.currentTarget),
        $input = $button.closest('form').find('input[name="'+$button.attr('name')+'"]');
    if(!$input.length){
        $input = $('<input>', {
            type:'hidden',
            name:$button.attr('name')
        });
        $input.insertAfter($button);
    }
    $input.val($button.val());
});
stephenr85
  • 151
  • 1
  • 4
1

I like @slashingweapon 's approach, but why not even shorter, like this?

$("button.positive").click(function () {
    var result = $(this).parents('form').serialize() 
        + '&' 
        + this.name
        + '='
        + this.value
    ;
    console.log(result);

    return false; // prevent default
});

Only if the server generates non-ascii button names or values, it would be like this:

$("button.positive").click(function () {
    var result = $(this).parents('form').serialize() 
        + '&' 
        + encodeURI(this.name)
        + '='
        + encodeURI(this.value)
    ;
    console.log(result);

    return false; // prevent default
});
PaulH
  • 2,918
  • 2
  • 15
  • 31
0

Shorter way:

$('form').submit(function(e) {
    var data  = e.originalEvent.submitter.name + '=' + e.originalEvent.submitter.value + '&' + $(this).serialize();
    e.preventDefault()
    //continue with ajax
});
ISO MCodD
  • 49
  • 1
  • 5