Reputation: 67
I'm really new to Backbone, and I've looked everywhere to try and figure this out. Fundamentally I get how Models, Views, Collections and Templates work together, but for some reason I just can't get my Collection to render in a template. Using Firebug, I get a "this.model is undefined"
Here's my code:
(function($) {
window.Category = Backbone.Model.extend({});
window.Categories = Backbone.Collection.extend({
url: "src/api/index.php/categories?accounts_id=1",
model: Category
});
window.categories = new Categories();
categories.fetch();
window.CategoriesView = Backbone.View.extend({
initialize:function () {
_.bindAll(this,"render");
this.model.bind("reset", this.render);
},
template:_.template($('#tpl-category').html()),
render:function (eventName) {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
var testTargetvar = new CategoriesView({ el: $("#collection") });
})(jQuery) ;
This is the data that my REST service generates:
[
{
"name": "Web Design",
"id": 0
},
{
"name": "Web Development",
"id": 0
},
{
"name": "Waste Management Solutions",
"id": 0
}
]
The "fetch" that I'm using does show the fetched data in Firebug.
And lastly, here's my template:
<div id="collection"></div>
<!-- Templates -->
<script type="text/template" id="tpl-category">
<span><%=name%></span>
</script>
I've verified that all the necessary scripts, jquery, backbone, underscore, etc. are being loaded onto the page properly.
Upvotes: 1
Views: 1932
Reputation: 26837
I don't see where you're setting the model
property of the view object. Your view constructor also seems to be confused between whether it represents the collection of categories (as suggested by the #collection
selector) or a single category (as suggested by the template and use of the model
property). Here is a working example that should help guide you to your complete solution:
( function ( $ ) {
var Category = Backbone.Model.extend( {} );
var Categories = Backbone.Collection.extend( {
url : "src/api/index.php/categories?accounts_id=1",
model : Category
} );
var categories = new Categories( [
{ name : "One" },
{ name : "Two" },
{ name : "Three" }
] );
var CategoryView = Backbone.View.extend( {
initialize : function () {
_.bindAll( this,"render" );
this.model.bind( "reset", this.render );
},
template : _.template( $( '#tpl-category' ).html() ),
render : function ( eventName ) {
this.$el.empty().append(
$( this.template( this.model.toJSON() ) ).html()
);
if ( ! this.el.parentNode ) {
$( "#collection" ).append( this.el );
}
return this;
}
// render
} );
var view, views = {};
categories.each( function ( category ) {
view = new CategoryView( {
tagName : 'span',
model : category
} );
view.render();
views[ category.id ] = view;
} );
} )( jQuery );
In this case I've simply manually populated the collection with several models in lieu of your fetch
method. As you can see, I instantiate a view for each model and pass the model object as the model
property.
In the render
method I empty the view element (this.el
/ this.$el
), then render the template and append the content of its root element to this.$el
. That's so I get the new content without wiping out the element itself. Then, for the purposes of this example, I test whether the element is already in the document, and if not I append it to #container
.
Upvotes: 1
Reputation: 4463
I always load my templates in my functions...that might help..
initialize: function(){
_.bindAll(this, 'render');
this.template = _.template($('#frame-template').html());
this.collection.bind('reset', this.render);
},
render: function(){
var $stages,
collection = this.collection;
this.template = _.template($('#frame-template').html());
Upvotes: 0