1

I've been racking my brain over this issue for a few days and cant come up with a decent solution.

I have the following model

{
  "id": "123",
  "key1": "foo",
  "key2": "bar",
  "metadata": {
    "height": 1,
    "width": 1  
  },
  "userPrefs": [
     {
       "name":"firstName",
       "displayName":"First name",
       "required":true,
       "dataType":"text",
       "defaultValue":"enter first name",
       "value": ""
     },
     ......
  ]
}

My view uses this model, and specifically the userPrefs, to create an edit form. So for example the userPrefs would generate an input like so

<input type="text" id="firstName" name="firstName" value="" placeholder="enter first name" required />

A user may then enter a value for first name - e.g. "John" and click save. I need to map this form data back to the model before issuing a PUT request.

So I hijack the submit event and do

this.$('form').serializeArray()

this returns me an array of key/value pairs e.g.

[{"firstName": "John"}]

Now the issue I'm having is how best to map these value's back into the correct userPref in the model.

I toyed with the idea of 'assuming' 5 userPrefs would result in 5 inputs. I could then just use an iterator with an index to update the correct userPref. But as we know, an unchecked checkbox wont be submitted, so a simple iterator wont work.

Then I tried taking each serialised value and looping through the userPrefs for a match. But this would still fall over with the checkbox issue mentioned above.

Can anyone see an elegant solution to this?

  • Is there a better json structure I should be using to get round this issue? perhaps a separate model containing only userPrefs
  • How will I know if a user has unchecked a checkbox and be able to update my model
redeye
  • 173
  • 8

2 Answers2

1

I came up with a fairly simple solution in the end.

var self = this;
var userPrefs = this.model.get('userPrefs');

// loop through the prefs and update one at a time....
_.each(userPrefs, function(pref, index) {       
   var item = self.$('#' + userPrefs[index].name); // userPref DOM item
   if (item[0].type === 'checkbox') {
      userPrefs[index].value = item[0].checked;
   } else {
      userPrefs[index].value = item[0].value;
   }
});

// update the model 
this.model.set('userPrefs', userPrefs);

Because I used each userPref to build the form in the first place, I can loop through them and query the dom.

I can then insert the value back into the model.

It has 2 downsides that I can see

  • I'm updating the value in the model regardless of whether it has actually changed
  • It has a hard coded check for checkboxes

But for my use case this is acceptable.

redeye
  • 173
  • 8
0

Here is the solution that I can think of. First thing is you should not have simple JSON as your model rather have an association (one-to-many, model to userPrefs). Have a look at Backbone Associations to establish the relationship. In Backbone Associations context you need to have a AssociatedModelcreated for your outer model and userPref and then add userPrefs collection into your outer model. (This is explained in Backbone Associations tutorials.)

When you create edit form from a specific userPref model store the id of this model somewhere in the form (a hidden field or data attribute) so that you can use it later to find the respective userPref model from userPrefs collection and update accordingly.

Hope this helps.

Niranjan Borawake
  • 1,628
  • 13
  • 20
  • Thanks for the suggestion. I like the idea of using nested models and associations to improve the architecture. However Im not sure how it would solve the issue of mapping form data back into the model? Maybe I'm missing something? – redeye Sep 19 '13 at 08:54
  • I have already explained it in the second para. Please have a look at the tutorials to set the model back to the your collection of `userPrefs`. – Niranjan Borawake Sep 19 '13 at 18:40