Backbone.js - instantiate Models/Views from exisiting html Backbone.js - instantiate Models/Views from exisiting html jquery jquery

Backbone.js - instantiate Models/Views from exisiting html


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:

  1. you get your existing html elements through jQuery. If your model's view is based on a tagName: 'li', then this is the kind of tag you need to retrieve here.
  2. You iterate through these tags to scrape the data that's in there that constitutes your models and create your models
  3. You create a view for each model, passing it the model and the base element. This was the problem I had: I was creating the view and only then trying to add it later through my_view.el = xxx. This doesn't work.
  4. You add your model to the collection

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)