A simple Backbone.Marionette tutorial

In this series of posts, we’ll cover writing a simple Backbone.js application as a primer. You can see the live result here. The original application is at https://github.com/ddellacosta/backbone.js-examples/tree/master/collections3 and all design assets (CSS, images, etc.) are from there.

This tutorial will show you how to use Derick Bailey’s Backbone.Marionette to build a simple application. But beyond getting a simple walkthrough, you’ll also be able to compare the app we write to the original, and see how Backbone.Marionette makes your life easier when writing Backbone apps.

So what’s the app going to be? It will simply allow cats to be ranked within a list: click “up” the cat is more popular, click “down”, the cat is less popular. Simple, no? Besides, on the internet, everybody likes cats ;-) If you want to skip ahead and checkout the code, it’s on Github and you can see it in action on this jsFiddle (the image assets have been replaced with placeholders). You can also follow along by checking out out each git commit.Update (June 2013): I’ve written a book on Marionette. It guides you through developing a complete Marionette application, and will teach you how to structure your code so large apps remain manageable.

Also, since this tutorial was written, Marionette has evolved with new functionality and better techniques to write scalable javascript apps. These are naturally covered in the book.

First steps

Since this is a tutorial, we’ll start with all the necessary static assets already in place (CSS, libraries, etc.). So go ahead and grab the zipped archive containing all you need to get started, or get the initial commit from github.

The first thing we’ll do is include our application within a javascript file that we include in index.html. Within that file, we’ll start a Backbone.Marionette application, and add a region to it (code):

MyApp = new Backbone.Marionette.Application();

MyApp.addRegions({
  mainRegion: "#content"
});

This region corresponds to an area that we will use in our application. Since our application is simple, we’ll be using only one. However, more complex apps will be able to use multiple regions to better breakdown the application’s complexity, using e.g. one region for the navigation menu, another for the main content, etc. The way we set the region is by passing a jQuery selector to the area we want to use. In this particular example, we want to use the DOM element with id “content” (which you can see in the index.html).

So now that we have a region to display things, what are we going to display? I mentioned it earlier: a leader board for cats. Which means we’re going to need to store information about cats, but also that we’re going to be dealing with multiple cats…

Models and collections

Backbone was designed mainly to build RESTful javascript apps, and it follows this RESTful architecture on the front end: we’re going to store our cats in Backbone models. Although we’re not going to be communicating with a server in our case, Backbone provides handy mechanisms to store model modifications on the server: Backbone.sync allows you to (e.g.) call cat.save() and the cat’s JSON representation will be sent to the server for storage.

So what do these models look like? We’ll, let’s go ahead and create a model for our cat (code):


AngryCat = Backbone.Model.extend({});

The code is deceptively simple: all we need to do is extend a Backbone class, and we get lots of goodies for free… As you can see, when you extend a Backbone Model, you need to provide a javascript object. For now, we’re simply providing an empty object with “{}”.

Remember how we’re going to deal with multiple cats? We’ll need some construct to deal with that, and that’s where Backbone collections come in. Collections also provide many niceties, some of which we’ll cover later. Let’s write the collection to store all of our cats (code):


AngryCats = Backbone.Collection.extend({
  model: AngryCat
});

This time you’ll notice that we didn’t simply provide an empty object when extending Backbone’s Collection. The reason is that a Backbone collection needs to know what king of models it contains. In our case, the collection contains cats, so all we need to do is declare our AngryCat model within the object we use to extend.

Now that we have everything in place to start managing our cats, we still need to display them.

Views

What are views in Backbone? Well, for starters, they’re very different from what you might have encountered in other frameworks (such as Rails). In Rails, views simply generate HTML that gets sent to the client. In Backbone, we use template for that role, and views act more like observers: they monitor changes in the applications state (data changes to models, user interactions, etc.) and update the view accordingly.

The only view mechanism Backbone provides is the plain vanilla Backbone.View. Backbone.Marionette, on the other, provides several different view types to choose from.  Since we want to display a collection of cats, we are going to use Backbone.Marionette’s CompositeView and ItemView. I’ll briefly cover both of them, but Derick Bailey (Backbone.Marionette’s author) covers devoted a blog post to the topic.

Backbone.Marionette.ItemView

The item view is, according to the documentation, “a view that represents a single item”. In our case, we’ll use it to represent a single cat in our collection. Since we’re going to display all of our cats within a table, this item view will essentially render a table row.

Backbone.Marionette.CompositeView

We’re going to use this view to render our collection. We already have an ItemView to render a single cat, so this view will render the table (headers, etc.) and then add one row for each cat in the collection by rendering the ItemView.

Backbone.Marionette does a lot behind the scenes for us. By using the composite view to render the collection, we don’t need to worry about updating the view when our collection changes (if we add a model instance, for example): the CompositeView does that on its own.

It you’ve glanced at the docs, you might have noticed the Backbone.Marionette also provides a CollectionView. If we’re going to display a collection, why not use that? Well, the simple answer is that the collection view is designed to simply render the collection (i.e. render one ItemView per model), without any fluff. We want to go slightly further, since we want the collection to have surrounding HTML (namely the table tags, headers, etc.).

So now we know what we’re going to use to display our collection. But how are we going to generate the HTML proper?

Templates

To generate HTML, Backbone uses templates: HTML skeletons that we will fill in with data from a model (e.g.). Templates would be the Backbone equivalent to the views Rails uses.

Let’s start with the template for the entire collection, which will be a table (code):


<script type="text/template" id="angry_cats-template">
  <thead>
    <tr class='header'>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</script>

You can see that this template is simply put within the HTML body using a script tag that has a content-type of “text/template”. The reason for doing so is that the DOM element will be easily selectable using jQuery (which is why the template has an id), but the content-type prevents the browser from doing anything with it.

This template will enable us to have a table with a single column containing the cat’s name. So now, we can move on to writing the template used to create individual rows (code):


<script type="text/template" id="angry_cat-template">
  <td><%= name ></td>
</script>

Same concept here as above: a script tag with an id and a special content-type. The addition you see here are the “<%=  %>” tags which will be familiar if you’ve used ERB before: they interpret the code between them. In this case, we’re simply going to print the “name” attribute of the model that is passed to the template.

Now that we have our templates, let’s write the view code that uses them.

Back to views

First, we’ll write the ItemView that will display a single cat (code):


AngryCatView = Backbone.Marionette.ItemView.extend({
  template: "#angry_cat-template",
  tagName: 'tr',
  className: 'angry_cat'
});

We need to specify a few things when declaring the ItemView. First, which template we’re going to use (which is a mandatory requirement). Then, we can specify some (optional) properties to control the HTML that gets rendered.

At this point, let’s take a small break to Backbone’s rendering. When a view is rendered, Backbone will create a DOM element that you can then manually insert into the document. If you look at a few Backbone tutorials, you’ll typically see that at work in a view’s render method.

Backbone.Marionette does a lot of cool things for us, and as a consequence our ItemView doesn’t have a render method visible. In other words, we haven’t had to declare a render method, because Backbone.Marionette already does that for us, and the created DOM element will get added to the document with our CompositeView.

So now that you know some of what goes on when a Backbone view gets rendered, the next properties will make more sense to you. The className is simply an HTML class that gets added to the element Backbone creates, so our item will have “class=’angry_cat'” in its HTML tag.

Speaking of the HTML tag, the plain vanilla tag the Backbone uses when creating an element during a view render is a “div”. Since we’re going to display our cats within a table, that wouldn’t suit our needs: we need a “tr” tag to be generated as the DOM element instead, and that is what we demand with the “tagName” property.

Now, onto the CompositeView (code):


AngryCatsView = Backbone.Marionette.CompositeView.extend({
  tagName: "table",
  id: "angry_cats",
  className: "table-striped table-bordered",
  template: "#angry_cats-template",
  itemView: AngryCatView,

  appendHtml: function(collectionView, itemView){
    collectionView.$("tbody").append(itemView.el);
  }
});

The same properties are being defined as for the ItemView, with the addition of “itemView”. Since our CompositeView will be rendering a collection, we are telling it which ItemView to use to render each model within the collection.

In addition, since we aren’t just going to be dumping the generated HTML at the end fo the template, but in the middle, we have to specify how HTML should be instered into our template with the appendHtml function. As you can tell, we’re not asking for much: we just want it dumped within the “tbody”.

UPDATE: Since writing this post, Marionnette has been updated, and the CompositeView’s behavior has changed slightly. You now need to the view to rerender the portion displaying the collection when the latter is sorted. See this commit.

Now that we have templates and views defined, let’s display something already!

Initializers

Right after we start our app, we’ll want to have our list of cats displayed. For this purpose, we’ll add a simple initializer (code):

MyApp.addInitializer(function(options){
  var angryCatsView = new AngryCatsView({
    collection: options.cats
  });
  MyApp.mainRegion.show(angryCatsView);
});

This initializer will receive any options we send to our application when we call its “start” method (which we haven’t done yet). What our initializer does is straightforward: create a new view with our cats, and display it.

Starting the application

Pretty straightforward also (code):


$(document).ready(function(){
  var cats = new AngryCats([
    { name: 'Wet Cat' },
    { name: 'Bitey Cat' },
    { name: 'Surprised Cat' }
  ]);

  MyApp.start({cats: cats});
});

Once the DOM is ready, we create a collection of cats populated by cat models we create simultaneously. Then, we simply start our application by passing in the cats collection, and voilà! The first milestone for our leader board is done (and should look something like this): we can display a list of models.

Now’s a good time for a break, but in the next post, we’ll add functionality to this (momentarily) boring app.

This entry was posted in Backbone.js, Backbone.Marionette. Bookmark the permalink.

12 Responses to A simple Backbone.Marionette tutorial

  1. Chris Hoffman says:

    Awesome post. Can’t wait for the next one, where you hopefully go into event binding.

  2. david says:

    Yup, the next installment will cover event binding :-)

  3. Johannes Hiemer says:

    Great post. Perhaps a small side note. I am currently a beginner with BbMarionette and I was a bit confused where to put the template stuff, because from other projects I always knew that there was a separate template folder.
    Now I see you put it into the index.html. Are you going to split things up in later parts of the tutorial?

    What would be interesting for me as well, would be some kind of subrouting and modularization for e.g. cats, dogs and so.

  4. Tres says:

    Not much of an improvement compared to plain backbone and much less understandable.

  5. david says:

    @Tres
    I disagree. Although a simple example doesn’t highlight Marionette’s advantages, I find it does make Backbone development simpler. For example, using only Backbone, how would you manage redisplaying the cats in the proper order when their rank changes? You could listen to changes to the collection and rerender the list, but it would mean writing boiler plate code that Marionette provides for free. In other words, I find Marionette makes it much easier and cleaner.

    In addition, having a CollectionView display your items means you don’t have to write more boiler plate code to display new items, rerender modified items, removed deleted items, etc… Initializers are also great when you need to fetch data from the server in the background while your application starts up (e.g. a list of categories), and Marionette routers (which I haven’t covered yet) are perfect for progressive enhancement.

    Are there any specific sections in this post you find confusing? Or is it just the framework?

    Much like generating a simple “about me” page with Rails would probably make someone think “this sucks, PHP makes outputting text really easy, I’ll use that”, I agree that the app in this post is very basic and doesn’t fully leverage Marionette, but I wanted something really simple for beginners. Naturally, if you’re just building a trivial site, it might not be worth including Marionette.

    That said, I’ve also rewritten the example at http://www.atinux.fr/backbone-books/ to use Backbone.Marionette. I’m going to do a writeup soon, and that will propably be a better showcase of how Marionette helps with managing complex Backbone applications.

  6. david says:

    @Johannes
    Yes, you could put the templates in a separate folder also.

    Routing and such will be covered in another tutorial, that will cover the rewriting of this exmaple: http://www.atinux.fr/backbone-books/

    In the meantime, you can see how Derick Bailey (Marionette’s creator) manages mulitple sub apps with Marionette routing/modularization: https://github.com/derickbailey/bbclonemail

  7. Charles says:

    Nice tutorial :)

    Could you make an example for using all this in a “bigger environment”? I mean using different modules with loose dependencies.

    Im asking because I read about some patterns for bigger javascript applications and there the mediator pattern was described so modules will not communicate directly but over the mediator. Now Im asking myself if this backbone.marionette event aggregator is the same as this mediator and if it could be used for managing multiple modules.

  8. david says:

    Yes, I’ve rewritten and expanded http://www.atinux.fr/backbone-books/ to use as an example, and will write up a tutorial on the subject soon.

    In the meanitme, if you just want to see the code for a larger app, you can look at https://github.com/derickbailey/bbclonemail which was written by Derick Bailey (Marionette’s author) as an example app to showcase Marionette.

    To answer your question more directly, the event aggregator is used as a mediator. In the second part of this tutorial (http://davidsulc.com/blog/2012/04/22/a-simple-backbone-marionette-tutorial-part-2/), you use events to trigger rank changes in the collection. Since this is implemented using the event aggregator, the different objects remain loosely coupled. If you want to compare with an example that doesn’t use a mediator, you can look at the original source code here: https://github.com/ddellacosta/backbone.js-examples/tree/master/collections3

    So hang on, and soon you’ll have a brand new tutorial to dig into ;-)

  9. Joakim says:

    Now this is very good tutorial. It would be perfect if there was instructions how to use fetch with this to get the data wich is is always little trickier due to async nature. I have created app where Views and collection are setup just like in this tutorial and otherwise its like bbclonemail.contactsapp.js + bbclonemail other structure

    What should be put in to xxs.showXXX = function(){ } and what goes to
    yyy.addInitializer

    The problem is that if you want to load and refresh the data from server and rerender how to do it? It gets updated only after second call to showXX(I put collection rerender to fetch succes to corret this, is this correct approach?) Another issues is that if you navigate directly to the url which routes to app in question then its shows every item twice, allthough showXXX is called only once and data also is fethced once, however if you come from another app everything is working fine.

  10. david says:

    You’ll probably want to check out my new tutorial, which is more advanced and covers fetching data. Read about it here: http://davidsulc.com/blog/2012/05/06/tutorial-a-full-backbone-marionette-application-part-1/

    Another way to solve issues with views being displayed before data has been fetched is to use collections that trigger callbacks. Derick Bailey does that in BBCloneMail: he creates a special collection type that triggers callbacks (https://github.com/derickbailey/bbclonemail/blob/master/public/javascripts/bbclonemail.collection.js) and then he creates callbacks on the controller actions that can get triggered and need to display data before it might be ready (see https://github.com/derickbailey/bbclonemail/blob/master/public/javascripts/mail/bbclonemail.mailapp.js#L73-80)

    Hope this helps !

  11. david says:

    @Charles

    The new tutorial is up at http://davidsulc.com/blog/2012/05/06/tutorial-a-full-backbone-marionette-application-part-1/

    It covers writing a bigger app, and using “sub apps” to swap out functionality in a loosely coupled way (among others).

  12. Pingback: Skeleton of a JavaScript web application « honeysoft

Comments are closed.