2
votes

I have a collection of objects which will be updated in bulk (not necessarily all at the same time, but more than one).

Therefore I need to send updates to the server in bulk (i.e. not one request for each updated object), and I need to do partial updates (i.e. only update objects which have changed).

Problems I have come across:

  1. There is no save() method on a Collection (strange considering it has a fetch() method)
  2. There is no built in tracking of models that have changed in a Collection since the last sync with the server.

Is there a clean, elegant way to achieve this?

I have researched and tried a few things, but all solutions are rather kludgy and over-complicated - which is unacceptable for a framework which is meant to simplify these sort of things.

Surely there is a decent way to do such a common thing in Backbone. Or should I use another framework e.g. Angular JS?

2
Why you need to update your collection items in bulk? Can they really be changed at the same time in your app? If no, then the common practice is to call model's save method once some item is changed. - hindmost
@hindmost yes they can be changed at the same time. There is a list of the items with checkboxes to select items, and the user can perform changes on all the selected items at once (e.g. changing the status of 10 items at once - I don't want my server getting 10 ajax requests for that) - developerbmw
Then you definitely have to change the structure of your app data. You shouldn't build collection on model containing single boolean value (checkbox checked state). Instead of using collection in your case it's better to use single model containing array of checkboxes' states. - hindmost
@hindmost the model does not contain the boolean checkbox state - this is only part of the UI. The model contains useful data, the checkboxes are in the UI for the user to select which models they wish to manipulate. - developerbmw

2 Answers

1
votes

You can just build an array of the JSON representation of the models. Something like this.

Backbone.Collection.prototype.save = function()
{
    var data = [];
    for (var n = 0; n < this.length; ++n)
    {
        data.push(this.models[n].toJSON());
    }

    // save data through jQuery
    console.log(data);
};

var col = new Backbone.Collection();
col.add({status: true});
col.add({status: false});
col.save();

You can add some model.hasChanged() check to prevent unnecessary savings.

0
votes

Just to help anyone who finds this question, this is what I ended up using (based on @joconja's answer):

Backbone.Collection.prototype.saveChanges = function() {
    var data = [];

    for (var i = 0; i < this.length; ++i) {
        if (this.models[i].hasChanged()) {
            var changes = this.models[i].changedAttributes();
            changes.id = this.models[i].get('id');
            data.push(changes);
            this.models[i].changed = {};
        }
    }

    Backbone.ajax({
        url: this.url,
        method: 'PUT',
        contentType: 'application/json',
        data: JSON.stringify(data)
    });
};