How to switch views using Backbone.js

Introduction

When we started developing with Backbone.js, we had some trouble setting up a basic application that simply switches between views. There are great tutorials explaining what a Router is used for and the documentation gives you a good place to start, but we didn’t find a tutorial that explained how to use this in real life applications. To make things worse, some of our jQuery events inside the views stopped working once a view was switched and some CSS styles did not apply as they were supposed to.

The View

To keep this tutorial simple, we put our content inside index.html. The view content is written inside a <script> tag with type="text/html" and an id so it can be loaded with a simple jQuery selector. You probably want to use a template engine like _.template and an AMD-loader like Require.JS for dealing with this, but there will be another blog post about that.

<script id="view-id" type="text/html">
	This is the view content.
</script>

As mentioned above, we had some issues with disappearing jQuery events once another view was loaded. In order to fix this, we have to override the default behavior of the Backbone View’s remove() function.

// Override View.remove()'s default behavior
Backbone.View = Backbone.View.extend({
	remove: function() {
		// Empty the element and remove it from the DOM while preserving events
		$(this.el).empty().detach();

		return this;
	}
});

The Backbone View, which is in fact more like a Rails Controller, is initialized with the id of the respective template <script> tag and renders the content into a new <div> (because we didn’t specify the el property).

var ContentView = Backbone.View.extend({
	/*
	 * Initialize with the template-id
	 */
	initialize: function(options) {
		this.template = options.template;
	},
	
	/*
	 * Get the template content and render it into a new div-element
	 */
	render: function() {
		var content = $(this.template).html();
		$(this.el).html(content);

		return this;
	}
});

The Router

The router is the piece of code that navigates between your views. It is initialized with the DOM element that should display the content when switching between views, and initializes the View classes as created above.

var ApplicationRouter = Backbone.Router.extend({
	initialize: function(el) {
		this.el = el;
		
		this.loremView = new ContentView({template: '#lorem'});
	},
...

In order to switch between views, we keep track of the current view, detach it, move the new view element to the DOM and render it afterwards. By doing this, we ensure that all CSS styles are already applied while the new view is being rendered.

...
	currentView: null,

	switchView: function(view) {
		if (this.currentView) {
			// Detach the old view
			this.currentView.remove();
		}

		// Move the view element into the DOM (replacing the old content)
		this.el.html(view.el);

		// Render view after it is in the DOM (styles are applied)
		view.render();

		this.currentView = view;
	},
...

The routes hash maps URLs to functions on the router. In this case, we want the lorem route to call the showLorem function.

...
	routes: {
		"lorem": "showLorem",
	},
	
	showLorem: function() {
		this.switchView(this.loremView);
	}
});

Putting it all together

Now all we have to do is create an instance of the ApplicationRouter and start the Backbone history.

<script type="text/javascript">
	var router = new ApplicationRouter($('#content'));
	Backbone.history.start();
</script>

The source code

You can find the complete example application in our public GitHub repository. Feel free to fork, comment and improve our solution.

64 notes

  1. viison posted this