Building Backbone.js apps with Backlift Part 1: Views and Templates

by Cole Krumbholz on Feb 19, 2013.
_________________

This is a beginning Backbone.js tutorial that will cover:

  • Setting up a bare-bones Backbone.js website
  • Creating a Backbone.js View, and
  • Using Handlebars templates to render dynamic content

During the tutorial we'll build a simple app that displays a randomly generated poem. You won't need any prior knowledge of Backbone.js to complete the exercises, but you should be familiar with Javascript, HTML and CSS, and know a bit about jQuery. We'll be using Backlift.com to host the app so you won't need to know a server framework like Rails, Django or Node.

This is the first tutorial of a series that covers the basics of Backbone.js, including Views, Models, Routers and working with a back-end. In the future we'll post follow up tutorials that discuss how to build a more complex Backbone.js app: a social photo gallery inspired by Pinterest.

If any questions about Backlift come up while you're working through this tutorial, please check out the Backlift docs.

Why Backbone?

This tutorial is meant to be a hands-on lab, not a lecture. So rather than getting into a lengthy discussion about the merits of Backbone.js, I'll simply provide a few links.

This Quora discussion contains a few good reasons for using Backbone.js. Also the answer to this Stack Overflow question provides a concise explanation of Backbone and MVC, though it's a touch out of date.

For more in-depth discussion about Javascript MV* check out this Smashing Magazine article. It provides a decent introduction to Javascript MVC and offers a comparative analysis of the different frameworks.

Once you're convinced that Backbone.js is worth learning, this tutorial is a good place to start.

Why Backlift?

Many tutorials assume that you'll be working with a server framework like Ruby on Rails or Node.js. These back-end frameworks require an entirely separate knowledge set. If you're a student or designer that is approaching web development from the front-end, you might want to tackle these concepts one at a time. Even if you're a full-stack developer who's familiar with a back-end stack, you may not want to install a different stack just to play around with Backbone.js.

Backlift is a back-end service that's made to work "out of the box" with Javascript MV* libraries like Backbone.js. It handles the grunt work required to set up a server and exposes an API for data persistence, validation and user authentication. Also, Backlift integrates with Dropbox and compiles your assets on the back-end. This means you can quickly launch a Backbone.js website and start playing around without installing anything on your computer. (Other than Dropbox of course)

If you're still unsure about learning Backbone with Backlift, just try the next two steps that demonstrate how easily you can get a Backbone.js website up and running.

Enough preamble, let's get started!

The setup

We'll start with a bare-bones project that contains Backbone.js and its dependencies. Backlift makes this part easy, just click the link below to download the project into your Dropbox. The ony prerequisite is that you have a Dropbox account and have the client installed on your computer.

When you click the "create" button, Backlift will begin downloading the project into your Dropbox folder. Once Backlift has finished creating the app, you can click the "view app" link to visit the app's public URL.

You have just published a Backbone.js website, congratulations!

Modifying your website with Backlift and Dropbox

Let's make a change to ensure that Backlift is working correctly, and to demonstrate the Backlift-Dropbox workflow. Navigate to your new app's folder within your Dropbox. It should be located in your Dropbox folder under Dropbox/Apps/Backlift/barebones. Once you've found it, open up the index.html file with a text editor and find the line that says:

<h1> Hello World! </h1>

Now replace it with:

<p>
  I postpone death by living, <br>
  by suffering, by error, by risking, <br> 
  by giving, by losing.
</p>
<small>Anais Nin</small>

Once you save the file, if the barebones website is still open in your browser, it should refresh in a few seconds. You don't need to tab over to refresh the page manually, it will update itself as soon as Backlift detects the changes.

Anatomy of the barebones Backbone.js app

Let's take a look at the other files in the project we just downloaded. The barebones folder in your Dropbox should contain the following files:

.
├── README.md
├── config.yml
├── index.html
├── libraries
│   ├── backbone-0.9.10.js
│   ├── backlift-reloader.js
│   ├── jquery-1.8.3.js
│   └── underscore-1.4.4.js
└── style.css

All the Backbone.js specific files are contained in the libraries folder. Backbone depends on jQuery and Underscore, so those scripts have been included along with backbone.js itself.

Two of the files are specific to Backlift. The backlift-reloader.js file is responsible for refreshing the website automatically when signaled by Backlift. The other Backlift specific file is config.yml which we will discuss in a moment. Otherwise this project earns its name: there's really not much to it.

Linking scripts and stylesheets

Backlift can help keep track of your scripts and stylesheets during development. If you take a look at the index.html you won't see any <link> or <script> tags. Instead, javascript and css files are linked automatically via the {{$ styles }} and {{$ scripts }} symbols. These are server template variables-- their contents will be filled in by Backlift when the page is rendered.

<!-- /index.html -->    

<!DOCTYPE html>
<html>
  <head>
    {{$ styles }}
    {{$ scripts }}
  </head>
  <body>

    ... 

  </body>
</html>

The contents of the server variables are determined by the scripts and styles properties within the config.yml file. A tag for each file matching one of the patterns will be added, in order, to index.html.

scripts:
- /libraries/backlift-reloader.js
- /libraries/jquery*.js
- /libraries/underscore*.js
- /libraries/backbone*.js
- /**/*.js

The order of the list is important because it ensures that Backbone's dependencies will be loaded first. Note that you can use a single wildcard * to match a part of a filename, and a double wildcard ** to match any path.

You can also add external URLs to scripts or styles list like so:

scripts:        
- //cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js
- /libraries/underscore*.js
...

You can prefix the resource with the protocol (http:// or https://), or use a double slash (//) which will match the protocol of your website. All Backlift websites are served via HTTP over SSL (using the https:// prefix).

Adding a Backbone View

We've got Backbone.js setup so let's put it to use. We'll start by rendering our poem using a Backbone View.

Backbone Views are a way to separate presentation logic from your application's "business logic." This separation of concerns makes it easier to modify how your website looks without effecting how it works. Backbone Views also offer shortcuts for creating dynamic user interfaces. For example the Backbone.View events property provides a convenient way to trigger behaviors as a result of user actions, like mouse click events. See Backbone.View.delegateEvents.

To add a View, create a new file called main.js at the root of the project folder, and add this code to define a PoemView:

// main.js

var poem = "<p>"+
  "  I postpone death by living, <br>"+
  "  by suffering, by error, by risking, <br>"+
  "  by giving, by losing."+
  "</p>"+
  "<small>Anais Nin</small>"

// Create the poem view class
var PoemView = Backbone.View.extend({
  render: function() {
    this.$el.html(poem);
    return this;
  }
});

// Add a poem view to the DOM
$(function() {
  var poemView = new PoemView();
  $("body").append(poemView.render().el);  
});

In the code above we've created a PoemView class that inherits from Backbone.View. PoemView has a single method, render(), that generates the HTML for our Anais Nin poem.

Every Backbone View has an el property that refers to the View's node in the DOM. It's the responsibility of the render() method to set the el property's html, thus filling in the View's content.

Note: $el and el both refer to the DOM node, but $el refers to the node wrapped in a jQuery object, and thus has access to jQuery methods such as html()

In the PoemView.render() function above, we set el to a string variable, poem that contains the HTML. If this were a real application, we'd probably want to create the HTML from a template using data from a database or API. We'll get to that later.

At the bottom of main.js we define an anonymous function that will be invoked when the page is finished loading. This function creates an instance of the PoemView class and uses jQuery to add it to the body of the page. Because render() returns this we're able to render the poem and get the resulting DOM node at once with poemView.render().el. This is a common Backbone convention.

Note: It's convenient for me to talk about View "classes" and "instances," because these concepts from classical object-oriented programming describe how Backbone Views are commonly used. However, Javascript is not a classical object oriented language, and the analogy doesn't describe how inheritance is implemented in Javascript. For more information about the Javascript inheritence model, check out this article.

Since we're using Backbone to render our view, we can now remove the poem's HTML from index.html. Please edit index.html so that it looks like this:

<!DOCTYPE html>
<html>
  <head>
    {{$ styles }} 
    {{$ scripts }}
  </head>
  <body>
  </body>
</html>

So far in this example we've taken a simple HTML document, cut out the content, pasted it into a Backbone View and rendered it back into the page. It may seem like unnecessary work just to render some static HTML, but in the process we've demonstrated the simplest use of a Backbone View.

In the next section we'll start to reap the benefits of Backbone as we add dynamic content to our website.

Rendering dynamic content with templates

Backbone excels at creating dynamic interfaces that change as the user interacts with the page. As a simple demonstration we'll modify our website to display a randomly generated poem that changes when clicked.

As a first step, we're going to move the poem's HTML from a string variable in main.js to a separate template. To accomplish this we'll use the Handlebars.js template library. To speed things up, I've created a new project that includes Handlebars.js, and the new template file. Download it by clicking the link below:

A few things have changed in this version of the poem app: The libraries folder now contains Handlebars.js. Handlebars has also been added to config.yml. Finally, there's a new app folder which contains the main.js script, style.css and a new poem.handlebars template:

.
├── README.md
├── app
│   ├── main.js
│   ├── poem.handlebars
│   └── style.css
├── config.yml
├── index.html
└── libraries

If you open app/poem.handlebars, you'll notice that it's just the HTML snippet containing the poem. Let's modify the template so that we can randomize the poem. Change poem.handlebars so that it matches this code:

<p>
  I postpone death by {{verbs.[0]}}, <br>
  by {{verbs.[1]}}, by {{verbs.[2]}}, by {{verbs.[3]}}, <br> 
  by {{verbs.[4]}}, by {{verbs.[5]}}.
</p>
<small>{{author}}</small>

Handlebars lets us specify template expressions using double curly brackets: {{}}. Now when we render this template, we can pass in values for the author and verb expressions in order to create a dynamic poem.

What's that crazy verb.[] syntax? That's the handlebars' "segment-literal notation" which can be used to pick an item from an array. You can read more about Handlebars expressions here.

At this point if you look at the poem website, you will find a blank page. If you open up your browser's Developer Console, you'll find an error. In Chrome I see the following:

Uncaught TypeError: Cannot read property 'verbs' of undefined 

Obviously we need to tell the template what values to substitute for the expressions we defined above.

Open up the `app/main.js' and create a random list of verbs by adding this code at the top:

var verbList = _.shuffle(["working", "loving", "singing", 
                          "screaming", "eating", "drinking", 
                          "fishing", "smoking", "chillin'"]);

Feel free to add a few verbs of your own. Now change the PoemView.render() method so that it looks like this:

  render: function() {
    var params = { 
        verbs: verbList,
        author: "Randy T. Robot"
    };
    this.$el.html(Handlebars.templates.poem(params));
    return this;
  }

In the new render() method we create a params object with verbs and author properties to match the Handlebars template we created earlier. We pass those parameters to the Handlebars.templates.poem function, which will render the template into an HTML string using our data. Finally we use the results to set the contents of our view's el.

Where did Handlebars.templates.poem() come from? One of the ways that Backlift speeds up development is by automatically compiling templates and scripts on the back-end. Backlift knows what compilers to use based on the file extension of the source file. Any .handlebars file is compiled into a Javascript function by the Handlebars command line tool and added to the Handlebars.templates variable. If you weren't using Backlift, you could compile these templates yourself by installing the Handlebars npm package and having it monitor your files for changes.

As a final touch, lets add an event handler that randomizes the poem when it's clicked. Edit your PoemView definition so that it look like this:

var PoemView = Backbone.View.extend({
  render: function() {
    var params = { 
        verbs: verbList,
        author: "Randy T. Robot",
    };
    this.$el.html(Handlebars.templates.poem(params));
    return this;
  },

  // --- new stuff ---
  events: {
    "click": "randomize"
  },
  randomize: function() {
    verbList = _.shuffle(verbList);
    this.render();
  }
});

We've added an events object that will dispatch click events to the randomize() function. Now when we view the poem website, we should see a randomly generated poem. Clicking the poem will generate a new random poem. This is awesome.

Conclusion

This wraps up part one of our tutorial on basic Backbone.js. In this tutorial we've created a simple website that displays a randomly generated poem using a Backbone View, and a Handlebars template. In case you want to check your work, you can download the final product here:

Stay tuned for Part two of this tutorial in which we'll introduce Backbone Models and fetching data from a server. In addition, we'll start a more involved project: a Pinterest inspired photo gallery. Until then, happy Backboning.

Do you want to create your own Dropbox download buttons? Anyone can build templates that are deployable via Backlift. Just create a github repository of your own, and then include the github repo in a special Backlift URL like this: https://www.backlift.com/backlift/dropbox/create?template=<github-URL>&appname=<default-app-name>. When users click on this link, they'll be directed to a "create app" page that will let them download the project to their Dropbox.

You can follow me at @colevscode

Learn and Earn!

Sign up for great tutorials, guides, rants, raves and opportunities to earn more money!