I've started looking at backbone.js today as a way to better organize the code in my application.
I was wondering (conceptually - so reply with pseudocode by all means) how I would use my existing html to create Backbone Models (and Views).
All of the tutorials I've found consist of using a blank html template and then injecting in the content using ajax. I don't want to do this.
If I have a collection of books.
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>My Book Collection</title>
</head>
<body>
<head>
</head>
<body>
<ul id="bookCollection">
<li class="book" data-book-id="1"><input type="text" name="book_1_name" value="My Book A"/></li>
<li class="book" data-book-id="2"><input type="text" name="book_2_name" value="My Book B"/></li>
<li class="book" data-book-id="3"><input type="text" name="book_3_name" value="My Book C"/></li>
<li class="book" data-book-id="4"><input type="text" name="book_4_name" value="My Book D"/></li>
<li class="book" data-book-id="5"><input type="text" name="book_5_name" value="My Book E"/></li>
</ul>
</body>
</body>
</html>
At this stage I would like to start managing each book as a model, calling a function whenever book names are changed (just an alert in the function for proof of concept), and then calling a URL to sync changes to the model with my database.
Can anyone point me in the right direction for a way to do the above using existing html on a page?
If it makes a difference I plan on using mustache for my templating.
I was really trying to do the same thing as well and just found my way around it!
Was trying to build on a todo list example where I'd already have some todos on the page, want to bring them as models in my Todos collection and have them managed the same way it happens for elements that were added to a blank page.
The whole js code is pasted as a gist there https://gist.github.com/1255736 with comments to explain more.
The important part is on how to instantiate the collection. Basically:
Note: the collection is usually tied to a view later so that using collection.add will update the view as well. Since initialize is called in the constructor, the collection has not been bound yet and you won't duplicate elements in your HTML by adding them here.
// this is the important part for initializing from html!
khepin.Todos = Backbone.Collection.extend({
model: khepin.Todo,
// In this function we populate the list with existing html elements
initialize: function() {
_.each(
// get all the <li></li> todo items (the base for the todo view)
// and for each of them:
$('.todo'),
function(a){
// Create the model
var todo = new khepin.Todo();
// Find the todo's text
var task = $(a).find('span')[0];
task = $(task).text();
// set the model correctly
todo.set({
task: task
});
// create the todo view
var todoView = new khepin.TodoView({
model: todo,
el: a // the el has to be set here. I first tried calling new TodoView and setting the 'el' afterwards
// and the view wasn't managed properly. We set the "el' to be the <li></li> we got from jQuery
});
// Add this new model to the collection
this.add(todo);
},
this
);
}
})
Hope this helps!
Backbone's views are always bound to a specfic html element (the view's attribute el
). You could have something like a BookCollectionView
bound to ul#bookCollection
and a BookView
bound to li.book
, which should be fine with your current template structure.
You can map a Book
model to a view using a url to the model. If the model is fetched from that url and you have defined an event binding for the model change, the according view should refresh with the new model data. Same applies for the collection's url and a collection of books.
There are not many good tutorials on backbone out i guess, but study something like http://liquidmedia.ca/blog/2011/02/backbone-js-part-3/ or http://www.jamesyu.org/2011/02/09/backbone.js-tutorial-with-rails-part-2/. Guess it is easier if you can come up with some more concrete questions!
I had the same problem and solved it this way within the constructor of my main view (the ul list) - as of backbone 0.9.
I converted it in my mind from coffeescript syntax so please be gentle if there are some syntax errors.
myListView = Backbone.View.extend({
initialize: function() {
._each(this.$el.children(), function(book, i) {
new Backbone.View({
el: book,
model: this.collection.at(i)
});
});
}
});
and calling it like this:
new myListView({
collection: anExistingCollection,
el: $('#bookCollection')
});
It's important that the order of the collection 'anExistingCollection' is the same as your already generated list entries as this example relies on the same index.
(untested)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With