Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling input arrays in Express forms?

Let's say I have to edit a batch of objects of the same type on the same page:

//-jade
form(action='', method='POST')
    for each message_id in messages_ids
        input(type='text', name='message', id='#{message_id}')
        input(type='text', name='author',  id='#{message_id}')
    input(type='submit', value='Send')

I know I wont be able to process such form on backend 'cause of id -- it wont be sent to backend. However, is there a way to do it? I'd like to get something like this on backend:

//js
for (var i = 0; i <= req.body.message.length; i++) {
    console.log (
        'ObjectID: ' + req.body.message[i].id, //-? null, just to show what I'm trying to get
        'Message: '  + req.body.message[i],
        'Author: '   + req.body.author[i]
    );
}

It's pseudocode (it wont work). So, any ideas?

P.S. I'm getting how to do this without AJAX

like image 245
f1nn Avatar asked Sep 06 '13 04:09

f1nn


Video Answer


1 Answers

For bodyParser.urlencoded, if you set the extended option to true, attribute names of the format property[nestedProperty] will be interpreted by the bodyParser middleware as:

{ property: nestedPropert: $value }

Just be sure to initialize the middleware like so:

app.use(bodyParser.urlencoded({ extended: true });

Afterwards, change the above form declaration to have the message property be an object, instead of a string value, like so:

form(action='', method='POST')

    - for (var i = 0; i < messages_ids.length; i++)
        - var message_id = messages_ids[i]
        //- so we're treating each index like a property of `message`
        input(type='text', name='messages[#{i}][message]')
        input(type='text', name='messages[{#{i}}][author]')
        input(type='hidden', name='messages[#{i}][id]', value='#{message_id}')

    input(type='submit', value='Send')

And then, on the server side, request.body.messages would be an object, that looks like:

{
  "messages": {
    "1": {
      "message": $message1,
      "author": $author1,
      "id": $id1
    },
    "2": {
      "message": $message2,
      "author": $author2,
      "id": $id2
    } /* , ... */
  }
}

And then, you can easily convert request.body.messages into an array:

var messages = Array.prototype.slice.call(request.body.messages);

And now, you should be able to access each elements like so (note: I prefer a functional style, but I'll keep it consistent with yours):

for (var i = 0; i < messages.length; i++) {
  console.log({
    'ObjectId' + messages[i].id,
    'Message' + messages[i].message,
    'Author' + messages[i].author
  });
}

P.S.: if you're wondering of a functional style, then here it is:

messages.forEach(function (message) {
  console.log(
    'ObjectId' + message.id,
    'Message' + message.message,
    'Author' + messages.author
  );
});

Edit: special thanks to @eye_mew for pointing out that we need to set extended to true.

like image 165
Sal Rahman Avatar answered Oct 20 '22 01:10

Sal Rahman