I'm building a simple Backbone app where I mainly have a view with a list of books (book name + cover image) and another view where I want to add new books to the list.
When I use a sample data the view with the books renders properly, but when I try to add books to the list it doesn't work and I don't know which is the problem.
Here is the JSFiddle http://jsfiddle.net/swayziak/DRCXf/4/ and my code:
HTML:
<section class="menu">
<ul class="footer">
<li><a href="">List of Books</a></li>
<li><a href="#edit">Edit</a></li>
<li><a href="#about">About</a></li>
</ul>
</section>
<section class="feed"></section>
<script id="bookTemplate" type="text/template">
<img src="<%= image %>"/>
<h2 class="bookTitle"><%= title %><h2>
</script>
<script id="aboutTemplate" type="text/template"> About </script>
<script id="editTemplate" type="text/template">
<form id="addBook" action="#">
<label for="title">Book Title</label><input type="text" id="title">
<label for="image">Image Link</label><input type="text"/ id="image">
<button id="add-book">Button</button>
</form>
</script>
</div>
And the Backbone code:
app = {};
// Sample Data
var books = [
{title:'Imperial Bedrooms', image:'http://upload.wikimedia.org/wikipedia/en/thumb/e/e8/Imperial_bedrooms_cover.JPG/200px-Imperial_bedrooms_cover.JPG
},
{title:'Less than zero',
image:'http://d.gr-assets.com/books/1282271923l/9915.jpg'
},
];
//Router
app.Router = Backbone.Router.extend({
routes: {
'' : 'home',
'about' : 'about',
'edit' : 'edit',
},
home: function () {
if(!this.bookListView){
this.bookListView = new app.BookListView(books);
}else{
this.bookListView.render();
}
},
about: function () {
if (!this.aboutView) {
this.aboutView = new app.AboutView();
}
$('.feed').html(this.aboutView.render().el);
},
edit: function () {
if (!this.editView) {
this.editView = new app.EditView();
);
$('.feed').html(this.editView.render().el);
}
});
// Model
app.Book = Backbone.Model.extend({
defaults: {
title:'',
image:'',
}
});
// Collection
app.BookList = Backbone.Collection.extend ({
model: app.Book
});
// Book View
app.BookView = Backbone.View.extend ({
tagName: 'div',
className: 'book',
template: _.template( $( '#bookTemplate' ).html()),
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
// List of Books View
app.BookListView = Backbone.View.extend({
el: '.feed',
initialize: function ( initialBooks ) {
this.collection = new app.BookList (initialBooks);
this.render();
this.listenTo( this.collection, 'add', this.renderBook );
},
render: function() {
this.$el.empty();
this.collection.each(function( item ){
this.renderBook( item );
}, this);
},
renderBook: function ( item ) {
var bookview = new app.BookView ({
model: item
});
this.$el.append( bookview.render().el );
}
});
// Add books view
app.EditView = Backbone.View.extend({
tagName: 'div',
className: 'edit',
template: _.template( $( '#editTemplate' ).html()),
events:{
"click #add-book":"addBook"
},
addBook:function(e){
e.preventDefault();
var title = this.$el.find("#title").val();
var image = this.$el.find("#image").val();
var bookModel = new app.Book({title:"title",image:'image'});
},
render: function () {
this.$el.html(this.template());
return this;
}
});
// About View
app.AboutView = Backbone.View.extend({
tagName: 'div',
className: 'about',
template: _.template( $( '#aboutTemplate' ).html()),
render: function () {
this.$el.html(this.template());
return this;
}
});
});
var router = new app.Router();
Backbone.history.start();
I think the problem is related with the Home router, the app.BookListView and the app.EditView, but I'm not sure of that.
Any help is welcomed.
Thanks.
In this example..for simplicity's sake, define a global books collection.
app.books = new app.BookList(books);
Pass your books collection to editView & BookListView in your router:
home: function () {
if(!this.bookListView) {
this.bookListView = new app.BookListView({collection:app.books});
}
else {
this.bookListView.render();
}
},
edit: function () {
if (!this.editView)
this.editView = new app.EditView({collection:app.books}); // your book collection
$('.feed').html(this.editView.render().el);
}
In you editView you need to make a few changes to your addBook
function:
app.EditView = Backbone.View.extend({
// your other code above
addBook:function(e){
e.preventDefault();
var title = this.$el.find("#title").val(); //could use: this.$('#title').val()
var image = this.$el.find("#image").val();
// remove quotes to pass variables
var bookModel = new app.Book({title:title,image:image});
// this.collection is app.books, your book collection.
// this will trigger the add event in your BookListView.
this.collection.add(bookModel);
},
});
In your BookListView
make the following changes to the initialize
function:
app.BookListView = Backbone.View.extend({
initialize: function() {
this.render();
this.listenTo( this.collection, 'add', this.renderBook );
},
Here is a fiddle with the changes: http://jsfiddle.net/9R9zU/