Skip to content Skip to sidebar Skip to footer

Bubbling Events In Nested Backbone (marionette) Models / Collections

We have a large Marionette App, that uses Backbone.trackit to monitor unsaved changes in our Models. We now have some nested models, in fact we have a Model, with a Collection of M

Solution 1:

The events from models inside a collection already bubbles to the collection by default. So that's one thing solved and we just need to bubble events from a collection or another model inside a model.

One problem I see with bubbling events as-is up the hierarchy is that you then get false positive when you want to listen to that specific collection or model.

A way to avoid that is to namespace events that are bubbling up, but that may not work with trackit.

A simple implementation of a model that enables bubbling up events of arbitrary collections or other nested models:

varBubblingModel = Backbone.Model.extend({
    /**
     * Bubbles up any event triggered by 'object'.
     * @param {Backbone.Events} obj which implement the Backbone Events.
     * @param {String} key optional namespace name, default to 'nested'.
     */addNested: function(obj, key) {
        returnthis.listenTo(obj, 'all', function() {
            arguments[0] = (key || 'nested') + ':' + arguments[0];
            this.trigger.apply(this, arguments);
        });
    },
    removeNested: function(obj) {
        returnthis.stopListening(obj);
    }
});

and to use it:

var collection = new Backbone.Collection(),
    model = new BubblingModel();
model.addNested(collection, 'optional-key');

Any events from collection will be prefixed by its optional key or by the default nested string. A change:myAttribute event triggered by collection would be:

"optional-key:change:myAttribute"

Proof of concept with simple tests:

// The simple implementationvarBubblingModel = Backbone.Model.extend({
    /**
     * Bubbles up any event triggered by 'object'.
     * @param {Backbone.Events} obj which implement the Backbone Events.
     * @param {String} key optional namespace name, default to 'nested'.
     */addNested: function(obj, key) {
        returnthis.listenTo(obj, 'all', function() {
            arguments[0] = (key || 'nested') + ':' + arguments[0];
            this.trigger.apply(this, arguments);
        });
    },
    removeNested: function(obj) {
        returnthis.stopListening(obj);
    }
});

// Setting up a test with multiple nestingvar model5 = newBackbone.Model(),
    model4 = newBackbone.Model(),
    model3 = newBubblingModel({ model: model4 }),
    col2 = newBackbone.Collection([model3]),
    model2 = newBubblingModel({ col: col2 }),
    col1 = newBackbone.Collection([model2]),
    model1 = newBubblingModel({ col: col1 });

// Set which you want to bubble up.
model3.addNested(model4, 'model3-nested-model');
model2.addNested(col2, 'model2-nested-col')
    .addNested(model5);
model1.addNested(col1, 'model1-nested-col');

// listen from any model down the chainBackbone.listenTo(model2, 'all', function(eventName) {
    console.log("model2:", eventName);
});
Backbone.listenTo(model1, 'all', function(eventName) {
    console.log("model1:", eventName);
});

// trigger default or custom events
model3.set('test', 1);
model3.trigger('model3');
model4.trigger('model4');
model5.trigger('model5');
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>

Post a Comment for "Bubbling Events In Nested Backbone (marionette) Models / Collections"