The "change" event is not firing in the following code.
var PageView = Backbone.View.extend({
el: $("body"),
initialize: function(){
this.model.on("change:loading", this.loader, this);
},
loader: function(){
if(this.model.get("loading")){
this.$el.find('.loader').fadeIn(700);
}
else
this.$el.find('.loader').fadeOut(700);
},
});
var PageModel = Backbone.Model.extend({
defaults: {
loading: null,
},
initialize: function(){
this.set({loading:false});
},
});
$(function(){
var pageModel = new PageModel({});
var pageView = new PageView({model: pageModel});
})
It works if I'm adding this in the model's initialize function:
setTimeout(function() {
this.set({'loading': 'false'});
}, 0);
I can leave it this way, but this is a bug.
The situation explained
Here's the order the code runs:
initializefunction is called, setting theloadingattribute tofalse,"change:loading"The event handler is never called because the event never occurs after it was registered.
Quick fix
First remove the set from the model.
Then, after creating the view, set the
loadingattribute.Since the listener is now registered before the model's
loadingattribute is changed, the event handler will be called.Optimized solution
Use Backbone's best practices:
.listenToover.onto avoid memory leakselproperty on the viewA view is an atomic component that should only care about itself and its sub-views.
While in your case, it wouldn't matter much that you use the
elproperty on the view, it still goes beyond the responsibilities of the view. Let the calling code deal with passing the element to use for this view.Put the defaults where they belong.
Here we choose the
bodyas the element to use for the view, using theeloption, and then callrenderwhen ready.The event won't be triggered by the listener right away, instead, we use the
renderfunction to put the view in its default state. Then, any subsequent changes of theloadingattribute will trigger the callback.I have listed the most useful answers I've written about Backbone on my profile page. You should take a look, it goes from the beginning to advanced and even provides some clever Backbone components that solves common problems (like detecting a click outside a view).