The problem is reproduced in the following way:
Whenever I navigate back the models aren't rendered. I suppose that is because this events aren't triggered:
this.listenTo(this.collection, 'add', this.addOne);
this.listenTo(this.collection, 'reset', this.addAll);
This is my router:
routes: {
'' : 'home',
'home' : 'home',
'departments' : 'departments',
...
},
home: function(){
var view = new app.HomeView();
this.showView(view);
},
departments: function(){
var view = new app.DepartmentsView();
this.showView(view);
},
showView: function(view){
if (this.currentView){
this.currentView.clean();
}
this.currentView = view;
this.currentView.render()
$('#container').html(this.currentView.el);
}
And this is my clean method:
Backbone.View.prototype.clean = function () {
this.remove();
this.unbind();
_.each(this.subViews, function(subView){
subView.clean();
if(subView.onClose){ subView.onClose() }
});
};
This is the onClose method on subviews:
onClose: function(){
this.model.off('change',this.render);
this.model.off('destroy',this.remove);
console.log('unbinding');
}
I save all subviews on array and then close when navigating away. I really haven't identified the root cause of such problem.
I'm quite desperate because I have tried everything from Derick Bailey's posts and going through Backbone's docs and haven't been able to fix this.
------EDIT-------- The view is composed as:
<tr>
This is my repo if you want to take a look. Reproducing something minimal actually is a lot of code to post in a question. REPO
Ill appreciate help with this.
Here's what i suspect the problem is. Your Departments
collection is only instantiated once, app.Departments = new DepartmentList();
. Then in your DepartmentsView
init function, you assign this.collection = app.Departments;
This means that the second time you route to DepartmentsView
, you're assigning its collection to an existing collection, that already has models. When you call fetch()
, Backbone detects there are no new models (since you already have the models in the collection), and thus doesn't trigger the add events.
One thing you can do is call fetch with reset, fetch({reset:true})
. Then when the fetch succeeds, it'll clear the existing models and re-add them all, and trigger reset.
Reset is a bit wasteful since you already have the models. Another solution is to check if the collection contains any models in your init function, if it does then render them. Something like this
initialize: function(){
this.collection = app.Departments;
this.subViews = [];
if(this.collection.size() > 0)
this.collection.each(this.addOne, this);
this.listenTo(this.collection, 'add', this.addOne);
this.listenTo(this.collection, 'reset', this.addAll);
this.collection.fetch();
},
Then the fetch will add any new models it finds upon fetch success.
EDIT: Not the cleanest solution but it should work.
initialize: function(){
this.collection = app.Departments;
this.subViews = [];
if(this.collection.size() > 0)
this.preExisting = true;
this.listenTo(this.collection, 'add', this.addOne);
this.listenTo(this.collection, 'reset', this.addAll);
this.collection.fetch();
},
render: function(){
this.$el.html( this.template({title: 'Departamentos',header_fields: this.tableHeader}) );
this.$tbody = this.$('#rows');
if(this.preExisting)
this.collection.each(this.addOne, this);
return this;
},