Skip to content

Instantly share code, notes, and snippets.

@vidoss vidoss/gist:3354438
Created Aug 15, 2012

Embed
What would you like to do?
Backbone for server rendered markup!
This Gist is for the case where your html is generated on the server side, but you still want to use Backbone to manage
the incremental user actions. The idea is to parse the already rendered DOM and create the model / collection on the
first time, hence we can still follow the Backbone pattern to update models and the bindings reflect view and update server etc.
Lets do step by step for the infamous TODO application:
Step 1) Add a function dom2coll() to the AppView that will parse the rendered DOM and convert to data.
dom2coll: function() {
// To update model/view from already rendered DOM from backend.
return _.toArray(this.$("#todo-list li").map(function(idx){
return {
id: $(".view",this).data("id"), // from <div data-id="xyz" attribute in server markup.
title: $(".view label",this).text(),
done: $(this).hasClass("done"),
order: idx,
el: this // pass el as well.
}
}));
},
// In the initalize() of TodoApp change the fetch() to..
initialize: function() {
...
Todos.fetch({dom2coll: _.bind(this.dom2coll,this)});
...
}
Step 2) Override the "sync" in the TodoList to call above function, instead of going to server.
This way your model is clean of view specific details.
sync: function(method, model, options) {
// If no dom2data go the default route.
if (!_.isFunction(options.dom2coll)) {
return Backbone.sync.apply(this, arguments);
}
// update from already rendered DOM.
options.success(options.dom2coll());
}
Step 3) Modify addOne() in the AppView to not call append(view.render().el) when el already exists.
Pass "el" in the TodoView() constructor.
addOne: function(todo) {
var el = todo.get('el'),
attrs = {model: todo};
if (el) {
attrs["el"] = el;
todo.unset('el',{silent: true}); // unset - so model will be clean.
}
var view = new TodoView(attrs);
if (!el) {
// skip appends for doms already rendred.
this.$("#todo-list").append(view.render().el);
}
},
DONE! Now all the views and model objects are ready and events delegated. No append, No insert, No innerHTML. clean!
@pspeter3

This comment has been minimized.

Copy link

pspeter3 commented Aug 15, 2012

Just out of curiosity would you be forced back to server side rendering?

@vidoss

This comment has been minimized.

Copy link
Owner Author

vidoss commented Aug 15, 2012

I prefer server side rendering for a simple reason. The rendering code is running on a machine I have more control over.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.