I want my panels to re-render themselves when they are clicked.
However, when I perform a click I get the following:
Uncaught TypeError: Cannot call method 'get' of undefined
It appears that the "this" that I'm logging is in fact the model itself:
_callbacks: Object
_changed: true
_escapedAttributes: Object
_previousAttributes: Object
attributes: Object
cid: "c0"
collection: r.d
id: "f5589ba4-a0aa-dd86-9697-30e532e0f975"
__proto__: n
I'm having trouble figuring out why the appropriate "this" isn't preserved by passing my context into model.bind.
Here's my code:
// Models
window.Panel = Backbone.Model.extend({
defaults: function(){
return {
flipped: false,
};
},
toggle: function(){
this.save({flipped: !this.get("flipped")});
},
});
// Collections
window.PanelList = Backbone.Collection.extend({
model:Panel,
localStorage: new Store("panels"),
flipped: function(){
return this.filter(function(panel){ return panel.get("flipped"); })
}
});
// Global collection of Panels
window.Panels = new PanelList;
// Panel View
window.PanelView = Backbone.View.extend({
tagName: 'div',
template: _.template($("#panel-template").html()),
events: {
"click" : "toggle"
},
initialize: function(){
this.model.bind("change", this.render, this)
$(this.el).html(this.template(this.model.toJSON()));
},
render: function(){
console.log(this);
var flipped = this.model.get("flipped")
if (flipped){
$(this.el).addClass("flip");
} else{
$(this.el).removeClass("flip");
}
return this
},
toggle: function(){
this.model.toggle();
}
});
The backbone-y way of doing this is to use the _.bindAll(...)
function provided by underscore:
initialize: function(){
_.bindAll(this, "render");
this.model.bind("change", this.render)
$(this.el).html(this.template(this.model.toJSON()));
}
What _.bindAll
does is documented here, but it is essentially built exactly for this purpose. If you want to have this
properly set in all functions of the object, you can call _.bindAll(this)
with no list of functions. I tend to have this global bind function in most of my views.
I ran into the same issue and ended up using underscore.js's _.bind() method instead. I queried SO for a response, and it was the reply I got.
Try changing: this.model.bind("change", this.render, this)
To: this.model.bind("change", _.bind(this.render, this))
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