Search code examples
javascriptbackbone.jsbackbone-eventsdom-manipulationbackbone.js-collections

Backbone.js multiple tables data manipulation


I have 3 separate tables in my page and they all get filled on View Initialize and fetch their data from my backend REST Api. After fetching data i bind the reset to method called paint and inside that loop through the collection and construct the table.

paintSelected: function (collection, options) {
    collection.each(function (ch) {
        var view = new ChannelViewDetailed({model: ch});
        view.setOwner(collection);
        this.$el.find('#selected tr:eq(' + collection.indexOf(ch) + ')').after(view.render().el);
    }, this);
},

this constructs the whole table on my defined underscore template. all is fine at this point and i can handle remove and add data between the multiple collections on this page.

When i want to perform an exclude all or include all operation on this tables things get messed up, the view owners get lost due to loops that i have to make, duplicates show up in the list and ordering gets lost.

ChannelViewDetailed = Backbone.View.extend({
    tagName: 'tr',
    template: _.template($('#tpl-channel-row-detailed').html()),

    events: {
        'click td.del': 'deleteSelected'
    },

    setOwner: function (collection) {
        this.owner = collection;
    },

    render: function () {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },

    deleteSelected: function (e) {
        e.preventDefault();
        this.owner.remove(this.model);
        this.remove();
    }
});

please note that all that was mentioned above works fine when performing per item actions, but doesn't function as expected when i wan't to perform batch (include all / exclude all) operations.

this is a sample of exclude all method i've trying to accomplish.

excludeAllChannels: function (e) {
        e.preventDefault();
        var self = this;

        if (!$.isEmptyObject(self.selected)) {
            _.each(this.selected.models, function (item, index, items) {
                self.selected.remove(item);
            });
            $('#in-channels tr').has('td').remove();
            unsavedState = true;
        }
    }

Solution

  • Modification of an array you are currently looping through can cause unexpected results.

    https://jsfiddle.net/c0xpzq6v/

    var a = new Backbone.Collection(data);
    _.each(a.models, function(item) { a.remove(item); });
    

    Can be replaced by any of the following

    _.each(_.clone(a.models), function(item) { a.remove(item); });
    a.remove(a.models);
    a.reset();