0

So this is a bit of weird one, partially because it doesn't seem to be entirely consistent, but I'm sure that's probabaly my fault!

I have a very simple app that I built to populate a MongoDB collection of books - it's nothing but an HTML form and a submit button - and everything is working perfectly except for this one bug. One field in each document is an array of subjects (ex. ['quantum', 'astro', 'relativity']). These are selected with checkboxes in the form and then pushed to an array in my jscript, which is then used to define an object newItem

let subject = [];

$('input:checkbox').each((i, e) => {
  if ($(e).is(':checked')) {
    subject.push(e.id);
  }
});

const newItem = {
  auth1: $('input#auth1').val(),
  auth2: $('input#auth2').val(),
  editor: $('input#editor').val(),
  title: $('textarea#title').val(),
  desc: $('textarea#desc').val(),
  year: $('input#year').val(),
  subjects: subject,
  };

I then clean up any empty field (for example if there isn't a second author or an editor) and post then post newItem to the DB:

  const keys = Object.keys(newItem);

  keys.forEach((key, index) => {
    if (newItem[key] === '' || newItem[key] === undefined) {
      delete newItem[key];
    }
  });


  $.ajax({
    type: 'POST',
    data: newItem,
    url: '/items/newitem',
    dataType: 'JSON',
  });

The (slight) problem here is that when I do this, the field "subjects" in the new document somehow gets named "subjects[]". This isn't such a big deal, and I can work around it on the other side, but I would rather figure out why this is happening - partially because I'll have to go and manually change all my old docs and partially because it wasn't always doing this, so I don't want to work around the change only to find out that I've inadvertently 'undone' in later on.

I can't imagine this matters, but if it helps, here's my router to deal with the post request:

/* POST to newitem. */
router.post('/newitem', (req, res) => {
  const { db } = req;
  const collection = db.get('inventory');
  collection.insert(req.body, (err, results) => {
    res.send(err === null ? { msg: '' } : { msg: err });
  });
});

I'm pretty much a beginner here, but I've been playing around a bit. When I log the value of newItem the object seems to have a "subject" key, not "subject[]".

Thanks in advance to anyone who has any ideas!

EDIT: Forgot to mention that I'm using monk to deal with the db. I'm not doing anything more than simple document insertion and basic queries, so it seemed to be sufficient.

MikeD
  • 11
  • 3
  • Since `subjects` is an array, what format would you expect it to be serialised as for `application/x-www-form-urlencoded` transmission. How have you configured your request body handling middleware? – Phil Nov 06 '20 at 03:03
  • Quick side note here: use Mongoose for interaction with MongoDB. – Tony Drummond Nov 06 '20 at 03:11
  • 1
    @Tony: Oh sorry - forgot to add that! I've been using Monk because what I'm doing is so minimal. Might this be where it's from? @ Phil - I don't know what you're asking. – MikeD Nov 06 '20 at 03:28
  • In your Express app, you'll have something like `app.use(express.urlencoded(...))` (perhaps using `body-parser` instead). What does that piece of code look like? – Phil Nov 06 '20 at 03:36
  • @Phil Ah! Thanks for the clarificaiton. I have ```app.use(express.urlencoded({ extended: false }));``` and am not using body-parser. As I mentioned, I'm still a beginning with this stuff so wasn't entirely certain what these do/don't do. – MikeD Nov 06 '20 at 03:39
  • Change it to `extended: true` and it should start working as expected. Don't worry about `body-parser`, that's just the old way of handling request formats. `express.urlencoded()` and `express.json()` are the modern alternatives – Phil Nov 06 '20 at 03:40
  • Thanks! I wouldn't have thought to look that up for this at all. – MikeD Nov 06 '20 at 03:42
  • The alternative is to add `traditional: true` to your jQuery AJAX request but that's a legacy option too. – Phil Nov 06 '20 at 03:43

0 Answers0