0

I've got a form. In this form, a user can fill out a few fields, then click "Add". The data gets turned into an HTML element, and then the form gets (partially) cleared so that he can type some more data.

I'm trying to figure out how to store that data when he clicks "Add" so that it can be submitted later. Should I serialize (JSON? or is there a more compact representation--doesn't need to be human readable) it and store it in a hidden field? If so, what happens when he adds a 2nd object? I deserialize the old data, and then reserialize the 2 objects together? Seems inefficient.

Do I somehow clone the form, hide it, and update all the name attributes so they don't conflict, and then kill myself trying to parse these stupid things into an array later?

What's the best approach?

mpen
  • 272,448
  • 266
  • 850
  • 1,236

2 Answers2

2

Create a hidden field with an incremental numerical suffix somewhere in the name.

var fields = $('input[type=hidden][name^=foo_]', form).length;
$('<input type="hidden" name="foo_' + (fields + 1) + '">').val(val).appendTo(form);

Submit it the usual way, jQuery.serialize() and so on.

Finally intercept on it accordingly in the server side (semi-pseudo).

for (var i = 0; i < Integer.MAX_VALUE; i++) {
    var value = request.getParameter("foo_" + i);
    if (value == null) break;
    // ...
}

Note that multiple hidden fields with the same name is also allowed, but you're dependent on the server side technology used whether they will be gathered in the same order from the request as they appeared in the query string (the HTTP/HTML spec already mandates that they must appear in the same order in the HTTP query string as their respective HTML input elements appeared in the DOM tree). As far as I know, PHP and Servlet do this correctly (i.e. the values appear in the same order in the array of parameter values as they appeared in the HTTP query string).

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • The other fun part is that I want to allow users to remove them too. Then I'd have to loop over all those hidden forms and renumber them? – mpen Feb 09 '11 at 19:37
  • 1
    @Mark: I'd add another hidden field which represents the `Integer.MAX_VALUE` and increment it on every addition and use it in the name suffix of hidden field and in the server side as end condition of the loop. If value is null/empty, then it was been removed, but you could just ignore it and continue on. – BalusC Feb 09 '11 at 19:38
  • @BalusC: That sounds less painful. – mpen Feb 09 '11 at 19:46
  • Been there, done that. Related: http://stackoverflow.com/questions/2094618/changing-name-attr-of-cloned-input-element-in-jquery-doesnt-work-in-ie6-7 – BalusC Feb 09 '11 at 19:47
  • @BalusC: So... I should definitely create a new element rather than trying to clone it and change its name? – mpen Feb 09 '11 at 19:58
  • If you want to support IE7 (or even 6) as well, yes :/ – BalusC Feb 09 '11 at 20:02
0

This depends somewhat on how your server expects the data, which in turn depends on what language / framework you're using server-side. If your server can easily handle multiple fields with the same name, it's very straightforward. (This example uses jQuery for simplicity.)

function onAddMore() {
    var $form = $("#myForm");
    var $foo = $form.find("[name=foo]").eq(0); // the first (original) foo

    $form.append($foo.clone())
    $foo.val("");
}

When the user submits the form normally, your query will look something like foo=bar&foo=baz&foo=quux.

Here's an example of how to iterate over the values in Python CGI.

form = cgi.FieldStorage()

for foo in form.getlist("foo"):
    # do something with foo

Or in PHP (note that for PHP, the field must be named foo[]).

for ($_GET["foo"] as $foo) { // $_POST would work the same way, of course
    // do something with $foo
}
Ben Blank
  • 54,908
  • 28
  • 127
  • 156
  • As I was explaining to Yads, this won't work. It won't work for checkboxes or radio buttons, with any server side language. – mpen Feb 09 '11 at 20:27