I have a Backbone app that uses nested collections (at least that's how I think they're called).
In my particular case there are tabs and subtabs, and each tab (model) contains a collection of subtab (model).
For those who're more familiar with code, I'll write bellow my models and collections, and how subtabs are nested inside the tab model:
// Subtab Model
var Subtab = Backbone.Model.extend({
defaults: { label: undefined }
});
// Subtabs Collection
var Subtabs = Backbone.Collection.extend({
model: Subtab
});
// Tab Model
var Tab = Backbone.Model.extend({
defaults: { label: undefined, subtabs: new Subtabs}
});
// Tabs Collection
var Tabs = Backbone.Collection.extend({
model: Tab
});
Now, when I change a tab's attribute it fires the change event on the Tab
model and also on the Tabs
collection (quite normal, right?), but when I change a subtab's attribute, it fires the change event on the Subtab
model and Subtabs
collection (this is also normal) but it doesn't bubble up to the Tab
model (and to the Tabs
collection).
At least, I guess it should because a collection inside a model was changed and so the model was changed (but maybe I'm wrong and I'm not getting it).
Any suggestion on how can I achieve this behavior with Backbone?
Backbone. js trigger Event is used to invoke or callback the function for the given event or a space-delimited list of events. The subsequent arguments will be passed along to the event callbacks in order to trigger it.
js Event once() The event once method is just like event on method but it causes the bound callback to only fire once before being removed.
Backbone. Backbone has been around for a long time, but it's still under steady and regular development. It's a good choice if you want a flexible JavaScript framework with a simple model for representing data and getting it into views.
A change
event is triggered by Backbone when an attribute changes via set
. The event is then also triggered on the collection, as you have seen. But, the value of your subtabs
attribute is not changing at all, it is still the same object you created in defaults
. If you used tab.set('subtabs', new Subtabs);
you would get a change:subtabs
event, but you don't want to do that.
I think you would have to do something in your code to trigger a new event on your Tab model.
// Tab Model
var Tab = Backbone.Model.extend({
defaults: { label: undefined, subtabs: new Subtabs},
initialize: function(){
// listen for change in subtabs collection.
this.get('subtabs').on('change', this.subtabsChanged, this);
},
subtabsChanged: function(model) {
// trigger new event.
this.trigger('subtab:change', this, model);
}
});
Then you could listen for the event:
tabs.on('subtab:change', function(tab, subtab) {
console.log(tab.get('label'));
console.log(subtab.get('label'));
});
This will work, I think. But I guess I am wondering why you would listen to your Tabs collection for a change in the Subtabs. In most cases, it might be better to just listen for the change event on your Subtabs collection itself.
tab.get('subtabs').on('change', function(model){
// do something with model, which is a Subtab.
});
EDIT: http://jsfiddle.net/phoenecke/DvHqH/1/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With