Nested BackboneJS Models

Nested BackboneJS Models

Nested Models

  • The document storage concept of MongoDB implies using a similar concept at front-end side — i.e. you get a single document that might have a nested subdocuments
  • Single network request is required to get all your data with a nested document-like structure, pulling subdocuments from an API would require multiple network requests, you’d also configure and implement API endpoints for each such request
  • Breaking a document to sub-documents (and assembling them back) is a tedious and time-consuming
  • Conceptual simplicity of nested model is obvious — while technically it may be more difficult to implement and use a nested model, it might be easier to understand the design of an application data layer while working with intuitive terms that are appropriately reflected as nested models

Feel the pain

var data = {
name: 'Bob',
lastName: 'Flop',
email: 'bob.flop@email.com',
phones: [
{
label: 'Home',
number: 101
},
{
label: 'Work',
number: 102
}
]
};
var personModel = new Backbone.Model(data);
_.keys(personModel.attributes)
> ["name", "lastname", "phones"]
personModel.get('phones[0].label')
> undefined
var phones = personModel.get('phones');
phones.map(function(phone) {
// do stuff with phone
});
var phones = personModel.get('phones');
var phoneModels = phones.map(function(phone) {
var phoneModel = new Backbone.Model(phone);
return phoneModel;
});
console.log(phoneModels);
> [Backbone.Model, Backbone.Model]
  • No events propagation across the model, changing an attribute on phone model doesn’t trigger change event on person
personModel.on('change', function (e) {
console.log('person has changed');
});
phoneModels[0].set('number',999);
// no change in person
  • No validation happens for person model when phone model is changed, i.e. you need to implement distinct validation logic for phone and for person model in order to get the validation process happen as soon as some property of phone model changes.
  • Eventually we’d need to send the modified person model to backend, that will require to handle all the changes in phones sub-models and to send a unified single model to our backend servers.

The shine of nested model

  • Get access to nested data with no effort, using JS syntax:
var nestedPersonModel = new Backbone.NestedModel(data)
nestedPersonModel.get('phones[0].label')
> "Work"
  • Events are handled properly:
nestedPersonModel.on('change:phones',
function () {
console.log ("Person has changed");
});
nestedPersonModel.set('phones[0].label', 'Office');
> Person has changed
  • Validation works as expected:
// define validation - disallow duplicated phone labels
var NestedPersonClass = Backbone.NestedModel.extend({
validate: function (attrs, options) {
var uniqueLabels = _.uniq(_.pluck(attrs.phones, 'label'));
if (uniqueLabels.length !== attrs.phones.length) {
return 'Duplicated phone labels are not allowed';
}
}
});
var nestedPerson = new NestedPersonClass(data);
nestedPerson.set('phones[0].label', 'Work', {validate: true} )
> false

console.log(nestedPerson.validationError);
> "Duplicated phone labels are not allowed"

Messing with nested models

var SubCollection = Backbone.Collection.extend({
// sync data to the original nested model when needed
flushData: function(model, path) {
var arrayPlaceholder = [];
this.forEach(function(model) {
return arrayPlaceholder.push(model.toJSON());
});
model.set(path, arrayPlaceholder);
return model.save();
};

// bind the collection to the specific path of a nested model
bindToModel: function(model, path) {
var dataArray, item, i, len;
dataArray = model.get(path);
this.on('change', function() {
this.flushData(model, path);
});

this.on('remove', function() {
this.flushData(model, path);
});

for (i = 0, len = dataArray.length; i < len; i++) {
item = dataArray[i];
// create sub-models from the array elements of the nested model
this.add(item);
}
};
});

The sub-models utopia

  1. Be able to create a new sub-model from any path of the ‘big’, nested model. The newly created sub-model should behave like a distinct Backbone model, but is is also has to be tightly bound to its ‘parent’ in terms of data integrity, events propagation, validation etc.
  2. Be able to create a collection of sub-models from array-like members of a nested model, having all the bindings listed above working correctly.

--

--

--

I like coffee, web development and simple code. https://agoldis.dev

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

leetcode 128. Longest Consecutive Sequence

NodeJS- How to use Express.js

Highcharts Area range and line

Simple Pagination in Next.js using react-paginate

Rxjs, real-world examples (Part 1)

Looking For The Best API To Get Aluminium Rate In JSON Format?

I will be holding a short zoom meeting tomorrow,it a a short class of me saying thank you and i…

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Andrew Goldis

Andrew Goldis

I like coffee, web development and simple code. https://agoldis.dev

More from Medium

53. Maximum Subarray(Leetcode)

Here is how to debug 10x faster on production!

Real-time H-265 video stream encoding with c++ and libavcodec