Reputation: 13476
Here is my view:
define(
[
"jquery"
, "underscore"
, "backbone"
, "eventView"
]
, function($, _, Backbone, EventView) {
"use strict";
var TimelineView = Backbone.View.extend({
tagName: 'div'
, className: 'column'
, _EventViews: {} // Cache event views for reuse
, initialize: function() {
this.collection.bind('add', this.add);
this.collection.bind('reset', this.add);
}
, render: function() {
return this;
}
// Listen for additions to collection and draw views
, add: function(model) {
var eventView = new EventView({
model: model
});
// Cache the event
console.log(this._EventViews);
this._EventViews[model.get('id')] = eventView;
// Draw event
eventView.render();
}
});
return TimelineView
}
);
As you can see I set the _EventViews
property to contain an empty object. However when I call the add()
function console.log(this._EventViews)
returns undefined and the following statement fails.
Can anyone tell me why this is?
Upvotes: 0
Views: 1246
Reputation: 5060
The problem is that within add
, this
is not your TimelineView. See this article for an explanation of context in javascript: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this
You can solve this in a few different ways. The easiest in this situation is to use the third parameter of bind
or on
(these two are the same).
initialize: function() {
this.collection.on('add', this.add, this);
this.collection.on('reset', this.add, this);
}
Or use listenTo
instead.
initialize: function() {
this.listenTo(this.collection, 'add', this.add);
this.listenTo(this.collection, 'reset', this.add);
}
Also, your _EventViews
cache will be shared by all instances of TimelineView
. If that is not what you want, create it in initialize
instead.
initialize: function() {
this._EventViews = {};
this.listenTo(this.collection, 'add', this.add);
this.listenTo(this.collection, 'reset', this.add);
}
Upvotes: 2
Reputation: 1906
It works for me:
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone.js"></script>
<script>
var TimelineView = Backbone.View.extend({
tagName: 'div'
, className: 'column'
, _EventViews: {} // Cache event views for reuse
, initialize: function() {
//this.collection.bind('add', this.add);
//this.collection.bind('reset', this.add);
}
, render: function() {
return this;
}
// Listen for additions to collection and draw views
, add: function(model) {
var eventView = ({
model: model
});
// Cache the event
console.log(this._EventViews); // Prints: Object {}
this._EventViews[model.get('id')] = eventView;
// Draw event
eventView.render();
}
});
var a = new TimelineView();
a.add();
</script>
I think the problem is the .add()
method is invoked from the collection add
event. When you add a listener (with in backbone is done with the .bind()
function) you must bind
(on the native meaning) the function:
_.bindAll(this, 'add');
OR
this.add = this.add.bind(this);
You have to do it before you add the function as a listener:
initialize: function() {
_.bindAll(this, 'add');
this.collection.bind('add', this.add);
this.collection.bind('reset', this.add);
}
Upvotes: 1