149

It seems by default disabled input elements are ignored by $.serialize(). Is there a workaround?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
fms
  • 2,147
  • 4
  • 18
  • 16

9 Answers9

256

Temporarily enable them.

var myform = $('#myform');

 // Find disabled inputs, and remove the "disabled" attribute
var disabled = myform.find(':input:disabled').removeAttr('disabled');

 // serialize the form
var serialized = myform.serialize();

 // re-disabled the set of inputs that you previously enabled
disabled.attr('disabled','disabled');
user113716
  • 318,772
  • 63
  • 451
  • 440
  • 34
    worth considering `readonly` instead of `disabled` as mentioned by Andrew below. – andilabs Jul 23 '14 at 14:31
  • 1
    Here's the rationale: "Only "successful controls" are serialized to the string." - https://www.w3.org/TR/html401/interact/forms.html#h-17.13.2 – Meetai.com Aug 04 '20 at 22:13
  • In my case some weird magic was not reseting the disabled fields properly, so I used `.clone()` on the form, then just `.remove()` the clone instead of applying the disabled back on. – George Dimitriadis Apr 13 '21 at 15:33
103

Use readonly inputs instead of disabled inputs:

<input name='hello_world' type='text' value='hello world' readonly />

This should get picked up by serialize().

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrew
  • 11,068
  • 17
  • 52
  • 62
  • 1
    Great, just a note: the submit button is still clickable when read-only. – André Chalella Nov 07 '15 at 00:46
  • 5
    disabled prevents serialization, but readonly prevents validation – Jeff Lowery Aug 19 '16 at 22:28
  • another problem with readonly - doesn't work for checkboxes. With them rather use a class plus a change event for it: `jQuery( document ).on("change", ".disablethis", function(e) { e.preventDefault(); this.checked = !this.checked; });` – Fanky Sep 20 '21 at 09:17
15

You can use a proxied function (it affects both $.serializeArray() and $.serialize()):

(function($){
    var proxy = $.fn.serializeArray;
    $.fn.serializeArray = function(){
        var inputs = this.find(':disabled');
        inputs.prop('disabled', false);
        var serialized = proxy.apply( this, arguments );
        inputs.prop('disabled', true);
        return serialized;
    };
})(jQuery);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Krzysiek
  • 2,494
  • 16
  • 20
13

@user113716 provided the core answer. My contribution here is just a jQuery nicety by adding a function to it:

/**
 * Alternative method to serialize a form with disabled inputs
 */
$.fn.serializeIncludeDisabled = function () {
    let disabled = this.find(":input:disabled").removeAttr("disabled");
    let serialized = this.serialize();
    disabled.attr("disabled", "disabled");
    return serialized;
};

Example usage:

$("form").serializeIncludeDisabled();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aaron Hudon
  • 5,280
  • 4
  • 53
  • 60
5

Try this:

<input type="checkbox" name="_key" value="value"  disabled="" />
<input type="hidden" name="key" value="value"/>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
KennyKam
  • 187
  • 2
  • 3
  • Could you please elaborate a bit more and explain to the OP why this works? – Willem Mulder Oct 17 '14 at 07:59
  • I can explain it for you. If you still wanna have a disabled input field (for whatever reason), but you also wanna send the input name with the serialize() method. Then instead you can use a hidden input field (with the same value as your disabled input field), which serialize() doesn't ignore. And then you can also keep your disabled input field for the visibility. – superkytoz Dec 03 '14 at 21:27
4

I can see a few workarounds, but still no-one suggested writing your own serializing function? Here you go: https://jsfiddle.net/Lnag9kbc/

var data = [];

// here, we will find all inputs (including textareas, selects etc)
// to find just disabled, add ":disabled" to find()
$("#myform").find(':input').each(function(){
    var name = $(this).attr('name');
    var val = $(this).val();
    //is name defined?
    if(typeof name !== typeof undefined && name !== false && typeof val !== typeof undefined)
    {
        //checkboxes needs to be checked:
        if( !$(this).is("input[type=checkbox]") || $(this).prop('checked'))
            data += (data==""?"":"&")+encodeURIComponent(name)+"="+encodeURIComponent(val);
    }
});
David162795
  • 1,846
  • 3
  • 15
  • 20
3

Disabled input elements don't get serialized because 'disabled' means they shouldn't be used, per W3C standard. jQuery is just abiding by the standard, even though some browsers don't. You can work around this, by adding a hidden field with a value identical to the disabled field, or by doing this via jQuery, something like this:

$('#myform').submit(function() {
  $(this).children('input[hiddeninputname]').val($(this).children('input:disabled').val());
  $.post($(this).attr('url'), $(this).serialize, null, 'html');
});

Obviously, if you had more than one disabled input, you'd have to iterate over matching selectors, etc.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Jason Lewis
  • 1,314
  • 8
  • 13
0

In case someone don't want to activate them, then disable them again, you can also try to do this (I modified it from Disabled fields not picked up by serializeArray, from using a plugin to using a normal function):

function getcomment(item)
{
  var data = $(item).serializeArray();
  $(':disabled[name]',item).each(function(){
    data.push({name: item.name,value: $(item).val()});
  });
  return data;
}

So you can call them like this:

getcomment("#formsp .disabledfield");
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
maximran
  • 425
  • 4
  • 11
  • 1
    I tried your function and it does not produce the elements name or value. See example below; `code` 3: {name: undefined, value: ""} 4: {name: undefined, value: ""} – blackmambo Feb 02 '20 at 06:38
0

Just over Aaron Hudon :

Maybe you've got something else than Input (like select), so I changed

this.find(":input:disabled")

to

this.find(":disabled")
Carl Verret
  • 576
  • 8
  • 21