Skip to content

Ecce Signum

Immanentize the Empathy

  • Home
  • About Me
  • Published Works and Literary Matters
  • Indexes
  • Laboratory
  • Notebooks
  • RSS Feed

Day: May 2, 2014

Simple Backbone Marionette Example With AppRouter

2014-05-02 John Winkelman

This one took a little longer than the rest to put together, because I nearly broke my brain trying to figure out how routing worked. I found myriad code samples for setting up and using the router, but no one sample had everything I needed to put together a bare-bones app. Once i finally figured it out, the rest snapped together immediately. So without further ado – First, the Javascript file:

/* define the application */
var app = new Backbone.Marionette.Application();

/* add the main region to the application */
app.addRegions({
	appRegion: '#AppBase'
});

/* define the module we will be using to create this app */
app.module('RouteTest',function(module, App, Backbone, Marionette, $, _){
	"use strict";

	/* the layout for the main view */
	module.AppLayoutView = Marionette.LayoutView.extend({
		tagName: 'div',
		id: 'AppLayoutView',
		template: '#template-AppLayoutView',

		regions: {
			'contentRegion' : '#ContentRegion'
		},
		ui: {
			'navHome' : '#nav-home',
			'navInfo' : '#nav-info'
		},
		events: {
			'click #nav-home' : 'onNavHomeClicked',
			'click #nav-info' : 'onNavInfoClicked'
		},

		/* when the view initializes, call initRouter to */
		initialize: function() {
			this.initRouter();
		},

		/* once the DOM is ready, start the Backbone history manager.
			This will cause the application to synch up with the 
			current route of the browser, e.g. #home or #info.
			This must be called onRender instead of on initialize
			because it immediately tries to render the appropriate view
			into the contentRegion. Also: If you don't start the backbone
			history, the router won't work. */
		onRender: function() {
			if( ! Backbone.History.started) Backbone.history.start();
		},

		/* initialize the AppRouter, which synchs the application
			to the browser navigation */
		initRouter: function() {

			// cache reference to 'this' in the module scope
			var capturedThis = this;

			// assign route handlers to specific routes.
			// In this case, 'home' is triggered when the browser
			// visits index.html#home. Likewise index.html#info.
			// the empty set is for an address with no hash.
			var appRouteHandler = {
					'' : 'onHomeRoute',
				'home' : 'onHomeRoute',
				'info' : 'onInfoRoute'
			}

			// controller which contains the methods which
			// are used as route handlers. These are referenced
			// in the appRoutes object above.
			var appRouterController = {
				onHomeRoute: function() {
					capturedThis.onHomeNavigated();
				},
				onInfoRoute: function() {
					capturedThis.onInfoNavigated();
				}
			};

			// define an AppRouter constructor
			var router = Marionette.AppRouter.extend({});

			// create a new instance of the AppRouter
			// and assign the routes and controller
			var appRouter = new router({
				appRoutes: appRouteHandler, 
				controller: appRouterController
			});
		},

		/* called when the router sees that we have met the criteria
			to trigger the 'onHomeRoute' handler */
		onHomeNavigated: function() {

			// define and display an instance of the HomeLayoutView
			var homeLayoutView = new module.HomeLayoutView();
			this.contentRegion.show(homeLayoutView);

			// update the navigation
			this.$el.find('.navButton.active').removeClass('active');
			this.ui.navHome.addClass('active');
		},

		/* called when the router sees that we have met the criteria
			to trigger the 'onInfoRoute' handler */
		onInfoNavigated: function() {
			var infoLayoutView = new module.InfoLayoutView();
			this.contentRegion.show(infoLayoutView);
			this.$el.find('.navButton.active').removeClass('active');
			this.ui.navInfo.addClass('active');
		}
	});

	/* view definition for the 'Home' screen */
	module.HomeLayoutView = Marionette.LayoutView.extend({
		tagName: 'div',
		id: 'HomeLayoutView',
		className: 'contentLayout',
		template: '#template-HomeLayoutView'
	});

	/* view definition for the 'Info' screen */
	module.InfoLayoutView = Marionette.LayoutView.extend({
		tagName: 'div',
		id: 'InfoLayoutView',
		className: 'contentLayout',
		template: '#template-InfoLayoutView'
	});

	/* add initializer, which fires when the app starts */
	module.addInitializer(function(){
		var layout = new module.AppLayoutView();

		/* show the layout in the region we created at the top of this file */
		app.appRegion.show(layout);
	});
});

/* when the DOM for this page is available, start the application */
$(document).ready(function() {
	app.start();
});

And here is the HTML file, including the templates.

<!doctype html>
<html>
	<head>
		<title>Backbone/Marionette Routing Example Using AppRouter</title>
		<style type="text/css">
			body {
				background: #ffffff;
			}
			#AppBase {
				width: 600px;
				margin: 10px auto;
				padding: 0;
			}
			#AppLayoutView {
				float: left;
				width: 598px;
				margin: 0;
				padding: 0;
				border: 1px solid #808080;
			}
			h1 {
				margin: 0;
				padding: 0;
				float: left;
				width: 100%;
				height: 30px;
				text-align: center;
				font: 24px/30px courier;
			}
			#Navigation {
				float: left;
				width: 100%;
				height: 30px;
				background: #ededed;
				text-align: center;
			}
			#Navigation a {
				font: 16px/30px courier, monospace;
				color: #000000;
				text-decoration: none;
			}
			#Navigation .navButton.active {
				color: #ff0000;
			}
			#ContentRegion {
				float: left;
				width: 100%;
			}
			.contentLayout {
				float:left;
				width: 100%;
				margin: 0;
				padding: 0;
				
			}
			#HomeLayoutView {
				background: #edffed;
			}
			#InfoLayoutView {
				background: #ededff;
			}
			.contentLayout h2 {
				margin: 0;
				padding: 0;
				text-align: center;
				border-bottom: 1px solid #808080;
				background: #ffffff;
			}
			.contentLayout p {
				padding: .5em 1em;
			}
		</style>
	</head>
	<body>
		<!-- Base element for app -->
		<div id="AppBase"></div>

		<!-- main layout template -->
		<script type="text/template" id="template-AppLayoutView">
			<h1>Backbone/Marionette Routing Example</h1>
			<div id="Navigation">
				<a id="nav-home" class="navButton" href="#home">Home</a> : : : 
				<a id="nav-info" class="navButton" href="#info">Information</a>
			</div>
			<div id="ContentRegion">HELLO!</div>
		</script>

		<!-- home screen template -->
		<script type="text/template" id="template-HomeLayoutView">
			<h2>Home</h2>
			<p>This is the home view</p>
		</script>

		<!-- info screen template -->
		<script type="text/template" id="template-InfoLayoutView">
			<h2>Information</h2>
			<p>This is a page of information</p>
		</script>

		<!-- libraries -->
		<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
		<script type="text/javascript" src="js/underscore.js"></script>
		<script type="text/javascript" src="js/backbone.js"></script>
		<script type="text/javascript" src="js/backbone.marionette.js"></script>

		<!-- app code -->
		<script type="text/javascript" src="js/script.js"></script>
	</body>
</html>

By the way, the missing piece which ended up costing me the better part of a day was the Backbone.history.start() call in the onRender method in the main Layout view.

Posted in Programming comment on Simple Backbone Marionette Example With AppRouter

Personal website of
John Winkelman

John Winkelman in closeup

Archives

Categories

Posts By Month

May 2014
S M T W T F S
 123
45678910
11121314151617
18192021222324
25262728293031
« Apr   Jan »

Links of Note

Reading, Writing
Tor.com
Locus Online
The Believer
File 770
IWSG

Watching, Listening
Writing Excuses Podcast
Our Opinions Are Correct
The Naropa Poetics Audio Archive

News, Politics, Economics
Naked Capitalism
Crooked Timber

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

© 2025 Ecce Signum

Proudly powered by WordPress | Theme: x-blog by wpthemespace.com