0

I'm using express.js with the bodyParser middleware (which, is technically node-formidable, behind the scenes).

I'd like to take and create a form that represents inputs for each of the data elements listed here:

{
  "name" : "asdf",
  "children" : [
       { 
         "child_name" : "xyz1234",
         "size" : 12
       },
       { 
         "child_name" : "1234aszds"
         "size": 14
       }
      ]
 }

The number of children here will be dynamic, but I'd like to be able to add additional fields client-side, and have them map into req.body on the server.

Note, I'm looking for how to name the inputs in the client in order for the raw POST body to have the correct encoding to allow node-formidable to parse them out into an array.

tbjers
  • 564
  • 3
  • 13
Andrew Theken
  • 3,392
  • 1
  • 31
  • 54

2 Answers2

1

The general way to achieve this is as follows (excluding non-essential attributes for clarity):

<input name="name"/>
<input name="children[0[child_name]"/>
<input name="children[0[size]"/>
<input name="children[1[child_name]"/>
<input name="children[1[size]"/>

Note that the square brackets are not balanced, this is required due to a "bug" in the "querystring" package (or, at least it would seem so, as of August 20th, 2013).

But, if the square brackets are left unbalanced, as above, the result is that this will be parsed into the object structure requested in my original question (i.e. this will be made available as "req.body").

The benefit of this is that it does not require any Javascript to do any "pre-flighting" on form submission.

Andrew Theken
  • 3,392
  • 1
  • 31
  • 54
0

Using an HTML form with input fields will be problematic since there is no easy way to define the structure without parsing each field name to determine its place in the structure.

For instance, if you posted the following:

<form action="/post" method="post">
  <input type="text" name="data[name]">
  <input type="text" name="data[children][][child_name]">
  <input type="text" name="data[children][][size]">
  <input type="text" name="data[children][][child_name]">
  <input type="text" name="data[children][][size]">
  <input type="submit" value="Submit">
</form>

Formidable would interpret into this JSON structure:

[ [ 'data[name]', 'name' ],
  [ 'data[children][][child_name]', [ 'cname1', 'cname2' ] ],
  [ 'data[children][][size]', [ 'csize1', 'csize2' ] ] ]

To post deep structures this way, I would recommend using AJAX and posting a complete JSON object instead, which I have outlined below.

The following should allow you to copy all of the fields directly into req.body. I elected to use the .mixin() helper from the utile library.

var utile = require('utile')

var form = new formidable.IncomingForm()
  , fields = {}

form
  .on('field', function (field, value) {
    fields[field] = value
  })
  .on('end', function () {
    req.body = utile.mixin(req.body, fields)
  })

Based on your JSON in the question itself, you could then access your values like this:

console.log(req.body.children[0].child_name)

If you are looking for a native way of merging the objects, see Combine or merge JSON on node.js without jQuery for a way to do this.

Hopefully this answers the question and helps you out!

Community
  • 1
  • 1
tbjers
  • 564
  • 3
  • 13