Hey guys I am currently following a tutorial and learning backbone, but for some reason I cannot get anything besides the Backbone model to work. Everything underneath it such as the collection or view does not seem to respond when entering things in the console. This is currently my code, I cannot find anything wrong with it and it validates in JSLint. One thing I noticed though is that the video is from before the 1.0 update of backbone. I am using jade for the layout and will include the code below as well.
UPDATED: I am working with this now.
(function(){
//app can be the name of the project/app
window.App = {
Models: {},
Collections: {},
Views: {},
Templates: {},
Routes: {}
};
window.template = function (id) {
return _.template($('#' + id).html());
};
//Can get rid of the Collection and views out of the names of each
//User Model
App.Models.User = Backbone.Model.extend({
defaults: {
firstName: 'J.R.',
lastName: 'Smith',
email: 'jsmith@knicks.com',
phone: '212-424-6234',
birthday: '03/05/1982',
city: 'New York'
},
location: function(){
return this.get('firstName') + ' ' + this.get('lastName') + 'is currently in ' + this.get('city') + '.';
}
});
// list of users
App.Collections.UsersCollection = Backbone.Collection.extend({
model: App.Models.User
});
//User View
App.Views.UserView = Backbone.View.extend({
tagName: 'li',
events: {
'click .edit':
},
template: template('userTemplate'),
initialize: function() {
this.render();
},
render: function() {
var template = this.template(this.model.toJSON());
this.$el.html(template);
return this;
//always return this on render methods
}
});
// view for users
App.Views.UsersView = Backbone.View.extend({
tagName: 'ul',
initialize: function() {
},
render: function() {
this.collection.each(function(user) {
//user is the model associated to the new created user
var userView = new App.Views.UserView({model: user});
this.$el.append(userView.el);
}, this);
}
});
var userView = new App.Views.UserView({model: User});
$(document.body).append(userView.render().el);
})();
Jade layout page
doctype 5
html
head
title=title
link(rel='stylesheet', href='/css/style.css', type='text/css')
link(rel='stylesheet', href='/css/bootstrap-responsive.css')
link(href='/css/bootstrap.css', rel='stylesheet', type='text/css')
link(href='/css/font-awesome.min.css', rel='stylesheet', type='text/css')
script(src='/js/jquery.min.js', type='text/javascript')
script(src='/js/jquery.validate.min.js', type='text/javascript')
script(src='/js/script.js', type='text/javascript')
script(src='/js/underscore.min.js', type='text/javascript')
script(src='/js/backbone.min.js', type='text/javascript')
body
div#container
div#header
block content
include footer
Jade index page
extends layout
block content
h1= title
p Welcome to #{title}
script(src='/js/main.js', type='text/javascript')
script(id='userTemplate', type='text/template')
<%=firstName%>
button.edit Edit
<%=lastName%>
button.edit Edit
<%=email%>
button.edit Edit
<%=phone%>
button.edit Edit
<%=birthday%>
button.edit Edit
<%=city%>
button.edit Edit
A view's render method simply fills in the view's el, someone else has to add that el to the page that people will see. You're using tagName in your view:
tagName: 'li'
That just means that Backbone will create an <li> as your view's el, it doesn't mean that that <li> will be added to anything. The usual pattern is for render to return this:
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
and then whoever is calling render can add the el to the page with something like this:
var userView = new UserView({model: user});
$(whatever).append(userView.render().el);
I do my Backbone work client-side so I'm not sure how that would fit into your set up.
I think the problem lies here:
var userView = new App.Views.UserView({model: User});
$(document.body).append(userView.render().el);
Looking at your code I would expect an instance of App.Views.UsersView to be appended, and for it to be populated - in the code above you're pushing in { model: User } to an instance of a UserView instance rather than an instance of UsersCollection to an instance of UsersView.
Firstly your UsersView.render method should return this; in order to allow use of the .render().el pattern, UsersView handles creating and attaching instances of UserView for each model in the collection so you don't need to worry about this again.
render: function() {
this.collection.each(function(user) {
//user is the model associated to the new created user
var userView = new App.Views.UserView({model: user});
this.$el.append(userView.el);
}, this);
return this;
}
Then, the following looks right to me:
var users_data=[{
firstName: 'A',
lastName: 'Person',
email: 'a@knicks.com',
phone: '212-424-6234',
birthday: '03/05/1982',
city: 'New York'
},
firstName: 'Another',
lastName: 'Person',
email: 'another@knicks.com',
phone: '212-424-6234',
birthday: '03/05/1982',
city: 'New York'
},
firstName: 'A',
lastName: 'Person',
email: 'a@knicks.com',
phone: '212-424-6234',
birthday: '03/05/1982',
city: 'New York'
}];
var users = new App.Collections.UsersCollection( users_data );
var usersView = new App.Views.UsersView( users );
$( document.body ).append( usersView.render().el );