Reputation: 15251
var Text = Backbone.Model.extend({});
Texts = Backbone.Collection.extend({
model: Text,
url: '/data.json',
});
var TextsView = Backbone.View.extend({
initialize: function() {
_.bindAll(this);
this.render();
},
el: "#Texts",
template: _.template($('#TextTemplate').html()),
render: function(e){
_.each(this.model.models, function(Text){
var TextTemplate = this.template(Text.toJSON());
$(this.el).append(TextTemplate);
}, this);
return this;
}
})
var Texts = new Texts();
Texts.fetch();
var TextView = new TextsView({collection: Texts});
this gives me Uncaught TypeError: Cannot read property 'models' of undefined
and does not display anything on the page.
Upvotes: 2
Views: 82
Reputation: 10638
This this.model.models
should be this.collection
In your render method in your view, you should use this.collection.each
instead of _.each
function.
render: function(e){
this.collection.each(function(Text){
var TextTemplate = this.template(Text.toJSON());
$(this.el).append(TextTemplate);
}, this);
return this;
}
If you want to use _.each
function, then you will need to access the models array directly in your collection as @dfsq pointed out. This can be done by using this.collection.models
.
render: function(e){
_.each(this.collection.models, function(Text){
var TextTemplate = this.template(Text.toJSON());
$(this.el).append(TextTemplate);
}, this);
return this;
}
EDIT 2
Here are some reasons your fetch call may not be working. First check that you are using a web server, since ajax requests may be blocked for security reasons using file system. I know this is blocked in Chrome unless you change a certain setting. Not sure about Firefox.
The second reason is that the fetch call
is asynchronous. This means that mostly likely your data will not be loaded when you run initialize
This means you'll need to make the following adjustments. First you need to add a listener to the add event of your collection so that anytime an item is added, your view will be notified.
initialize: function() {
_.bindAll(this);
this.render();
// Listen to the `add` event in your collection
this.listenTo(this.collection,"add", this.renderText);
},
Next we need to add a function to your view that will render a single item
renderText: function(Text) {
var TextTemplate = this.template(Text.toJSON());
this.$el.append(TextTemplate);
}
Also to answer your other question about the user of this
in the each loop. The last parameter in the each function is the scope you want to use in the inside the callback function that executes. So if you use this
as the second parameter, it allows you to access your viewing using this
.
this.collection.each(function(Text){
var TextTemplate = this.template(Text.toJSON());
$(this.el).append(TextTemplate);
}, this);
If you don't add this
, then you'd need to do this:
var view = this;
this.collection.each(function(Text){
var TextTemplate = view.template(Text.toJSON());
$(view.el).append(TextTemplate);
});
Upvotes: 2