10

Couldn't find this anywhere, maybe someone knows or can make a suggestion.

I had a form with lots of <inputs>, I wanted to send that form with jQuery $.ajax functionality, so I did $('#myform').serialize() and send this as json.

Now my form is more advanced and has HTML5 data- attributes, that I want to send too, but .serialize() doesn't see them.

I tried putting them in <form> tag, <input> tags - nothing works.

What is the best practice to grab them and send with all the form data? I know about .serializeArray(), but how do I get all of the data- attributes that my <form> tag has attached serialized?

Sergey Telshevsky
  • 12,077
  • 6
  • 55
  • 78
  • 1
    You need to define how you expect these attributes to get serialised. Do you just want `data-foo="bar"` to get mapped to `foo=bar` ? Also, is there any reason they can't go into `hidden` input tags? – Alnitak Aug 23 '12 at 22:16
  • Since data- attributes can be called anything, you'll also need to specify which ones you want to serialize. – Mike Robinson Aug 23 '12 at 22:18
  • Technically - yes, I want to think of an easy way to do this, so that I could do `$('#myform').serialize()` and the string would have input values and `data-` attribute values serialized and escaped. It could be a custom function. – Sergey Telshevsky Aug 23 '12 at 22:19
  • @MikeRobinson *all* data attributes, if I would want to take only few, I would do it by hardcoding – Sergey Telshevsky Aug 23 '12 at 22:19
  • It's certainly doable, but there are a lot of questions still. How will you handle duplicate data attributes (e.g. data-id=1, data-id=2) on different elements. Should they be sent as an array, or associated with the name of the input element they were on? – Mike Robinson Aug 23 '12 at 22:22
  • @MikeRobinson never heard that it is valid to do so, but in any case, just make the last one overwrite the others. (as an easiest option) – Sergey Telshevsky Aug 23 '12 at 22:24
  • 2
    @Alnitak's idea of using hidden inputs seems like the right approach to me. – sissonb Aug 23 '12 at 22:24
  • @sissonb it is a really common solution used for years now and that's not what the point of the question is. – Sergey Telshevsky Aug 23 '12 at 22:27
  • 1
    possible duplicate of: http://stackoverflow.com/questions/5560293/hidden-inputs-vs-html5-data-attributes – Nope Aug 23 '12 at 22:46
  • @FrançoisWahl could you please tell me, where do you see the word `serialize` in the topic you've linked? – Sergey Telshevsky Aug 23 '12 at 22:49
  • @Vlakarados: As far as I can tell you are trying to post data located in data attributes. You want to serialise them automatically, which as far as a I know is not possibly automatically. The question I linked discusses the problems with posting data-attribute data and indicates hidden fields being in that case the best solution (not a work-around). If you don't like hidden fields, you can apply a work-around by writing your own function to read each data attribute into an object property, then serialise that object and post that along with your form data. – Nope Aug 23 '12 at 22:58

3 Answers3

9

Here's how it can be done. It might not be the best way, but it works the way it should work.

http://jsfiddle.net/Bvzqe/12/

HTML:

<form id="frm" data-id="123" data-list[one]="first" data-list[two]="second">

The serialization:

    var form = $('#frm');
    var dataarr = new Array();
    for(var i in form.data()) {
        var subarr = new Array();
        subarr['name'] = i;
        subarr['value'] = form.data()[i];
        dataarr.push(subarr);
    }
    var serialized = $.param(form.serializeArray().concat(dataarr));

It even allows you to have arrays of data- attributes such as

data-list[one]="first" data-list[two]="second"

URL encoded it may seem wrong, as it escapes square brackets, but I've tested this on the server side - it parses everything exactly as it should.

This is only for those that don't want to use <input type="hidden">

Sergey Telshevsky
  • 12,077
  • 6
  • 55
  • 78
  • This works and is the right way to go. I've used this sort of code in a couple of helper methods. A new "serializeDataArray()" jQuery extension and an AJAX post back method which includes three parts... the original form serialize array then serialize data attributes for both form and source/post back control. Not sure what the HTML 5 rules are on this but I think data attributes from both the (more global) form and (contextual) source element are necessary is most cases. – Tony Wall Mar 17 '15 at 12:04
  • Thanks for reminding me you can just use a hidden input lol – twan Feb 01 '21 at 12:28
  • Hello how to deserilize a JSON to data - attributes the reverse way – aggie Oct 05 '22 at 01:32
6

If at all possible you should store your additional values as hidden input fields (one per value) rather than as meta-data on other input fields. They'll then get serialized automatically as part of the form.

I won't write a serializer for you, as I think it's a bad idea. If you insist on sending the values to the browser as data- fields you could do this, though, to convert those data- fields into hidden inputs.

$('#myform:input').each(function() {
    var input = this;
    $.each($(input).data(), function(key, value) {
        $('<input>', {type: hidden, name: key, value: value}).insertAfter(input);
    });
});

Hey presto, hidden input fields that'll be automatically serialized!

Be aware that jQuery also uses .data() to store things like events. To avoid iterating over those objects you'd have to use the native DOM functions to retrieve the data- attributes, and not any data-related properties that have been stored on the elements.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • Sorry, that just will not do. That is not the answer to my question, that is a workaround. – Sergey Telshevsky Aug 23 '12 at 22:26
  • @Vlakarados no, putting your data in `data-` fields is the workaround. Using `hidden` fields is the _standard_ way of including additional (non-visible) data in a form submission. – Alnitak Aug 23 '12 at 22:27
  • it is a workaround for my question, rather than solution. I know that it is the standard way, but I asked how to serialize `data-` attributes not 'how to hide data from displaying on screen'. Hidden inputs were invented only because there were no js back then, no ajax. For a high-load project writing `` instead of ` data-key="value"` is using more bandwidth, greater load times. And I'm not even saying about ease of manipulating such data in JS. – Sergey Telshevsky Aug 23 '12 at 22:34
  • 4
    @Vlakarados yup, that's what I call a work around. You've invented a scheme for storing additional information in the form (because of minor concerns about page load times) that is _not_ supported by W3C `
    ` tags and then complain when the means to serialise that data doesn't exist?! Hidden fields weren't invented "because there was no AJAX", they were invented because _that's how you supply extra information in a form!_
    – Alnitak Aug 23 '12 at 22:37
  • @Vlakarados and FWIW, I could trivially write what you require - it would be around a dozen lines of code. But IMHO it would not be useful to do so. You are manufacturing a problem of your own making for no good reason. – Alnitak Aug 23 '12 at 22:39
  • 2
    Gotta side with @Alnitak on this, the bandwidth introduced by additional inputs is incredibly trivial. Hidden inputs will also work regardless of whether javascript is enabled (or broken). – Mike Robinson Aug 23 '12 at 22:40
  • Ok, guys, I've asked a normal question - "how can I seriealize data attributes". How do you think, are hidden inputs the answer to this question? I also mentioned that I've done a research on this topic and it's not covered anywhere. – Sergey Telshevsky Aug 23 '12 at 22:48
  • @Vlakarados don't you realise that the reason it's not covered anywhere is _because it's not a good idea!_ – Alnitak Aug 23 '12 at 22:52
  • @Alnitak I'm sure you've heard of other frameworks like knockout.js, that mostly use data- attributes for even basic things. What if in my current project all frontend system is based on these attributes, should I rewrite everything and use inputs? I see your point, I really do, but I did not ask if it was a good idea or not, I did not ask what other possibilities exist. – Sergey Telshevsky Aug 23 '12 at 23:02
  • @Vlakarados: Your question was `What is the best practice to grab them and send with all the form data?`. The answer is hidden fields. But you can apply a work-around and iterate throguh all data-attributes yourself and create an object to send along with your form post. Or use a framework if it exists that does it for you. If you find one, please post it as an answer as it definelty will help others in the future. – Nope Aug 23 '12 at 23:03
  • @Vlakarados sure, there are plenty of uses for `data-` attributes and properties. Knockout.js uses them, jQuery uses them. Using them to store form data isn't a valid use case for them! The very fact that those frameworks _do_ use them is even more reason for you not to! – Alnitak Aug 23 '12 at 23:04
  • Thank you for an edit, that's not what I wanted to see, but this **IS** an answer to my question, so thank you and upvoting of course. – Sergey Telshevsky Aug 23 '12 at 23:06
  • 1
    @Vlakarados you should note that I'm not getting any rep for this - I already hit the daily limit. I'm putting this much effort in because I seriously believe that your current implementation is incorrect. – Alnitak Aug 23 '12 at 23:16
  • That's why I'm arguing too, I hope you take no offense – Sergey Telshevsky Aug 23 '12 at 23:19
  • 1
    I have to side the Sergey here. I'm running up against the same challenge right now. Even though using hidden input elements is considered the standard, de facto way of tacking on additional data to a form, the big problem inherent in that method is that one can no longer associate data-* values with a particular form element. That is to say, once serialized, you end up with a flat map whose structure does not represent associations. What I'm probably going to end up doing is to write my own serializer that creates a JSON tree of the form. – Aquarelle May 13 '14 at 16:49
0

here is my func, get all data-* of element + support ignore array

Data2Params: function (el, ignoredAtt) {
    ignoredAtt = typeof ignoredAtt !== 'undefined' ? ignoredAtt : [];

    var data = {};
    for (var key in el.data()) {
        if (ignoredAtt.indexOf(key) === -1)
            data[key] = el.data(key);
    }
    return data;
}
dobs
  • 2,742
  • 2
  • 21
  • 19