-
-
Save juanghurtado/2949288 to your computer and use it in GitHub Desktop.
// Model | |
module.SampleModel = Backbone.Model.extend({}); | |
// View | |
module.SampleView = Backbone.Marionette.ItemView.extend({ | |
template : template_string, | |
// This trigger runs only the first time. After that, "click" event is not triggered (defaults to href="#") | |
triggers : { | |
'click .reload' : 'reload' | |
}, | |
initialize : function() { | |
this.bindTo(this.model, "change", this.modelChanged); | |
this.model.fetch(); | |
}, | |
modelChanged : function() { | |
// App has a Marionette.Region called "mainRegion" | |
App.mainRegion.show(this); | |
} | |
}); | |
// Init | |
var model = new module.SampleModel(); | |
var view = new module.SampleView({ | |
model : model | |
}); | |
view.on('reload', function() { | |
console.log('reload event'); | |
model.fetch(); | |
}); |
It doesn't seems to fix my issue. I must be doing something wrong, but I don't know what it is.
If I use View events instead of ItemView triggers it does not work neither.
May it is something related to the method I'm using to attach the view to the Region? https://gist.github.com/2949288#L20
Ah, actually, yes. That is a problem.
When you call region.show(this)
you are doing 2 things:
1 closing the current view
2 rendering and showing the next view
The process of closing the current view is going to completely destroy your view's DOM event and other event bindings, in order to properly clean up the references and release the used memory. In this case, the current view and the next view are one and the same, so you are destroying the DOM event handlers and they are never being re-created. Thus, the view's DOM clicking functionality disappears.
You don't need this line. It does far more than you want, and creates many problems in the process. Instead, you should be binding the model's "change" event to the view's render
method:
this.bindTo(this.model, "change", this.render, this);
This will re-render the view's contents any time the model changes, which will update the DOM with the new data the way you want. But it won't mess with any of the event bindings - DOM or otherwise.
Iin general, it's a bad idea to have a view know when and where to show itself. That knowledge belongs outside the view, at a higher level:
var view = new MyView();
MyApp.region.show(view);
So the view doesn't know where or when it will be displayed. The application, at a higher level, takes care of that concern.
Thanks a lot for your time, Derick. It's awesome to have people like you on the community. Kudos to you!
I'm still lost about this. I need to show my view once the model is fetch from the server, that's why I had it on the "change" event of the model itself. If I to the region.show(view)
outside of the "change" event it throws an error complaining about undefined vars that I'm using inside the template of the view (obviously, that vars don't exists yet because the model is being fetched).
How this simple requeriment should be approached?
You can defer the rendering and displaying of the model until after the data has been loaded, like this:
var model = new module.SampleModel();
var view = new module.SampleView({
model : model
});
// the "sync" event triggers after the data has been loaded from the server
model.on('sync', function() {
App.mainRegion.show(view);
});
model.fetch();
Oops… I feel like an idiot. Of course that is the way!
Thank you again, Derick. You deserve a donation on Marionette, sir!
and thank you! i really appreciate that :)
Are you sure that the event on the model is "sync". It does not trigger when doing it this way:
var weatherModel = new module.WeatherModel({});
var weatherView = new module.WeatherView({
model : weatherModel
});
weatherModel.on('sync', function() {
App.mainRegion.show(weatherView);
});
weatherModel.fetch();
Data is fetched from the server (checked on browser console). If I use "all" on model event, the callback is executed many times, but not when using just "sync".
I'm looking on Backbone.js events catalogue, but none of them seems logic (except "sync"). Maybe "reset", but it is just for Collections
Is this a better approach?
weatherModel.fetch({
success : function() {
App.mainRegion.show(weatherView);
}
});
I thought 'sync' was supposed to work like that... but the success callback would work certainly
this is likely caused by the
initialEvents in the
ItemView`.https://github.com/derickbailey/backbone.marionette/blob/v0.8.2/src/backbone.marionette.js#L143-147
when you fetch the model, a reset event is fired and the view will re-render itself. it seems the triggers are not being re-applied on re-rendering the view. can you log a bug in the issues list for this? I'll get it fixed in the next release (v0.9.2) of Marionette.
As a workaround for now, override the
initialEvents
events in your view definition so that it doesn't do anything: