Book Image

Backbone.js Blueprints

By : Andrew Burgess
Book Image

Backbone.js Blueprints

By: Andrew Burgess

Overview of this book

<p>Backbone.js is an open source, JavaScript library that helps you to build sophisticated and structured web apps. It's important to have well-organized frontend code for easy maintenance and extendability. With the Backbone framework, you'll be able to build applications that are a breeze to manage.<br /><br />In this book, you will discover how to build seven complete web applications from scratch. You'll learn how to use all the components of the Backbone framework individually, and how to use them together to create fully featured applications. In addition, you'll also learn how Backbone thinks so you can leverage it to write the most efficient frontend JavaScript code.<br /><br />Through this book, you will learn to write good server-side JavaScript to support your frontend applications. This easy-to-follow guide is packed with projects, code, and solid explanations that will give you the confidence to write your own web applications from scratch.</p>
Table of Contents (14 chapters)
Backbone.js Blueprints
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Writing some views


In simple applications like the one we're creating in this chapter, most of the Backbone code that we write will be in views. I think it's fair to say that views can be the most challenging part of a Backbone app, because there are so many ways that almost everything can be done.

It's important to understand that a Backbone.View instance and a screen full of web apps aren't the same thing. One view in the browser may actually be many Backbone views. The first view that we want to create is a list of all the posts; these will be links to individual post pages. We could do this in two ways: as one big view or as multiple smaller views put together. In this instance, we're going to be using multiple views. Here's how we'll break it down: each list item will be generated by its own view instance. Then, the wrapper around the list items will be another view. You can picture it as looking something like this:

The PostListView class

Let's start with the child views. We'll call this PostListView class. Naming views can be a little tricky. Often, we'll have a view for the collection and a view for the model, and we'll just append View to the end of their names, for example, PostView and PostsView. However, a model or collection will have multiple views. The one we're about to write is to list our models. That's why we're calling it PostListView:

var PostListView = Backbone.View.extend({
  tagName: "li",
  template: _.template("<a href='/posts/{{id}}'>{{title}}</a>"),
  render: function () {
    this.el.innerHTML = this.template(this.model.toJSON());
    return this;
  }
});

Just like Backbone.Model and Backbone.Collection, we create a view class by extending Backbone.View. We have three properties in the extending object that make up our PostListView. The first one to look at is the template property; this property holds the template that our view will render. There are plenty of ways to create a template; in this case, we're using the Underscore's template function; we pass a string to _.template, and it returns a function which we can use to generate the correct HTML. Take a look at this template string: it's regular HTML with variables placed within double curly braces.

Next, let's look at the render method. By convention, this is the method that we call to actually render the view. Every view instance has a property named el. This is the base element for the view instance: all other elements for this view go inside it. By default, this is a div element, but we've set the tagName property to li, which means we'll get a list item instead. By the way, there's also a $el property, which is a jQuery object wrapping the el property; this only works if we have jQuery included in our application.

So, inside our render function, we need to fill in this element. In this case, we'll do that by assigning the innerHTML property. To get the HTML output, we use the template we just wrote. That's a function, so we call it, and pass this.model.toJSON(). The this.model portion comes from when we instantiate this view: we'll pass it a model. Every model has a toJSON method, which returns a raw object with just the attributes of the model. Since our model will have the id and title attributes, passing this to our template function will return a string with those values interpolated into the template string we wrote.

We end our render function by returning the view instance. Again, this is just convention. Because of this, we can use the convention where we get the element for this view via view.render().el ; this will render the view and then get the el property. Of course, there's no reason you couldn't return this.el directly from render.

There's one more thing to address here, but it's about Underscore and not Backbone. If you've used the Underscore's template function before, you know that curly braces aren't its normal delimiters. I've switched from the default <%= %> delimiters, because those are the delimiters for our server-side template engine. To change Underscore's delimiters, just add the following code snippet to the top of our app.js file:

_.templateSettings = {
  interpolate: /\{\{(.+?)\}\}/g
};

Of course, you realize that we could make the delimiters whatever we want, as long as a regular expression can match it. I like the curly braces.

The PostsListView class

Now that we have the view for our list items, we need the parent view that wraps those list items:

var PostsListView = Backbone.View.extend({
  template: _.template("<h1>My Blog</h1><ul></ul>"),
  render: function () {
    this.el.innerHTML = this.template();
    var ul = this.$el.find("ul");
    this.collection.forEach(function (post) {
      ul.append(new PostListView({ 
        model: post 
      }).render().el);
    });
    return this;
  }
});

As views go, this is pretty simple, but we can learn a few new things from it. First, you'll notice that our template doesn't actually use any variables, so there's no reason for us to actually use a template. We could directly assign that HTML string as this.el.innerHTML; however, I like to do the little template dance anyway because I might change the template string to include some variables in the future.

Notice the second line of the render function: we're finding an ul element; the same ul element that we just made as a child element of our root element, this.el. However, instead of using this.el, we're using this.$el.

Next, we're looping over each item in the collection that we'll associate with this view (when we instantiate it). For each post in the collection, we will create a new PostListView class. We pass it an options object, which assigns the view's model as the current post. Then, we render the view and return the view's element. This is then appended to our ul object.

We'll end by returning the view object.