Backbone.js Views

In the following segment, we are gong to look at views in Backbone.js.

The files for demo and download for the following discussion can be found below if you’d like to follow along…

View Demo Download Files

What is a View?

As the name suggests, a “view” has to do with something you “view” on your screen (wow, what a concept!) :). But if you have done any programming in other languages before and you’re familiar with the Model View Controller software design pattern, the same pattern that Backbone.js follows (albeit very roughly), sometimes you have to take a moment to think about what is being referred to when talking about a view. Often times when you think of a “view” in an application framework such as CodeIgniter, ASP.NET MVC, or Django you tend to think of an entire rendered page of output (at least I do). Yes there are things like “partial views” and other components of MVC that don’t necessarily mean that a view is an entire rendered page, but that is just the tendency that I gravitate towards. When you are returning a view in frameworks such as those, you are often doing so in response to a browser’s request and routing them to a particular web page.

Views in Backbone.js are perhaps a bit different. Views in Backbone.js can really be thought of more as “DOM elements.” Just remember that general concept. It has helped me a lot while learning Backbone.js. It gets a little more complicated — especially since you can have views within views — but that’s a good general idea to keep in mind.

So let’s get into it. To create a view in Backbone you just have to extend the View class…

var ArtistList = Backbone.View.extend({});

Note: We are going to be creating a list of musical artists just as a demonstration.

We can just put our view statement in the markup below. If we were developing a Backbone application that we were going to use for production, we’d put our views into separate .js files and not directly in our page. But for our demo, this will suffice.

<!DOCTYPE html>
<html>
<head>
<script src="js/jquery.js" type="text/javascript"></script> 
<script src="js/underscore.js" type="text/javascript"></script> 
<script src="js/backbone.js" type="text/javascript"></script> 
</head>
<body>
<div class="list"></div>
<script type="text/javascript">
var ArtistList = Backbone.View.extend({ });
</script>
</body>
</html> 

Let’s define the DOM element that we want to house this view. All views in Backbone have an “el” property (which stands for element). If you don’t define this, Backbone will just use an empty <div> for “el”. But in our case, we are going to choose an element we already have put in the DOM.

var ArtistList = Backbone.View.extend({
    el: '.list'
});

We’ve created this “list” class but to use it we’re going to have to instantiate it. We can do this right after we define our class….

var ArtistList = Backbone.View.extend({
    el: '.list'
});
var artistList = new ArtistList();

If we ran this code… nothing happens. Why? Well it’s because we have to write some code for another important component of a view in Backbone.js: the “render” method. The render method is the place where we’ll define the markup that we’ll use for our view. Let’s modify our class so that it looks like the following…

var ArtistList = Backbone.View.extend({
    el: '.list',
    render: function() {
        var markup = '<p>Bone Thugs-n-Harmony</p><p>Mike Jones</p><p>Notorious BIG</p>';
        this.$el.html(markup);
    }	
});
var artistList = new ArtistList();

We now have a function that we can call to render our markup. We are using the jQuery HTML method to set the markup of our view. this.$el, or “This Dot Dollar El” phonetically, is a good term to keep fresh in your mind. It refers to the container element that is our Backbone view and by using this.$el, you can call all the jQuery that you want on it. If you don’t want to use a jQuery method and would just rather use regular JavaScript, you can just use this.el.

We actually have to call our render method to insert our view’s markup into the page.

...
var artistList = new ArtistList();
artistList.render();

Now if we refresh the page, we can see that the element is populated with our markup. Yay!

Events

We can also attach events to our views (or our DOM elements if that makes it a bit clearer). It wouldn’t be all that great if our apps were limited to just displaying things on the screen. We need to make them interactive. To do this, we can use the “events” property to define our events. Let’s modify our view so that it looks like the following…

var ArtistList = Backbone.View.extend({
    el: '.list',
    render: function() {
        var markup = '<p>Bone Thugs-n-Harmony</p><p>Mike Jones</p><p>Notorious BIG</p>';
        this.$el.html(markup);
    },
    events: {
        "click p" : "clickParagraph",
        "mouseover p" : "mouseOverEvent"
    }, 
    clickParagraph: function() {
        console.log('You clicked a paragraph element');
    },
    mouseOverEvent: function() {
        console.log('You moused over a paragraph element');
    }, 		
});
var artistList = new ArtistList();
artistList.render();

Look at that. Now if we mouse over or click on the text in our application, we can see that the different events are logged to the consode. The format that we use for events in views is this…

"type selector" : "method"

What does that mean? Well, that means that the first item in the property is the type of event that we’re doing (click, mouseover, mouseout, etc). What are the names of the events can you use here? In general, Backbone.js uses the same event naming as jQuery. So if you were looking for a list of Backbone view events, you could probably just look up a list of jQuery events and use those for events. The next thing you put after your event (separated by a space) is the selector. For our example above, we just used the <p> tags. as selectors — which is fairly general. If we wanted to get more specific we could do something like the following…

var ArtistList = Backbone.View.extend({
    el: '.list',
    render: function() {
        var markup = '<p>Bone Thugs-n-Harmony</p><p class="mike">Mike Jones</p><p>Notorious BIG</p>';
        this.$el.html(markup);
    },
    events: {
        "click p" : "clickParagraph",
        "click .mike" : "clickMikeJones",
        "mouseover p" : "mouseOverEvent"
    }, 
    clickParagraph: function() {
        console.log('You clicked a paragraph element');
    },
    clickMikeJones: function() {
        console.log('You clicked Mike Jones. Who?');
    },
    mouseOverEvent: function() {
        console.log('You moused over a paragraph element');
    }, 		
});
var artistList = new ArtistList();
artistList.render();

Notice how we added a class to one element in our render method and added an event based on that specific selector. Now that event will only fire when the element with that class is clicked. But because this is both a <p> element and has the class we defined an event for, *both* events will fire. You just have to be careful when defining your events in your applications and make sure that you’re not getting behavior that you don’t want by having events firing too often.

And of course, the third component to our view events is the actual method that we define inside of our view. This is the method that gets executed when our events happen. We can just add these events after the definitions in our events object and we can add as many of these as we want.

One thing of note, if you do not specify a selector, Backbone.js will use the entire container DOM element defined in the “el” property. So if we just added an event like the following…

"click" : "clickContainer",

…that event would fire every time we clicked anywhere inside of our .list element.

Templates

Another thing we can define in our view is whether or not to use markup found in a template. This becomes useful when we start populating our views (DOM elements) with dynamic data that we’re getting from the server. The way that we define a template is to create one in the page and then use the templating engine of Underscore.js to render it. In order for Backbone.js to function, Underscore.js needs to be loaded (something known as a dependency), so you can feel free use all the Underscore.js functions and methods that you want in Backbone without any concern because you know that it has to be loaded. So let’s change our page to the following…

<!DOCTYPE html>
<html>
<head>
<script src="js/jquery.js" type="text/javascript"></script> 
<script src="js/underscore.js" type="text/javascript"></script> 
<script src="js/backbone.js" type="text/javascript"></script> 
</head>
<body>
<script type="text/template" id="artistTemplate">
    <p>Bone Thugs-n-Harmony</p>
    <p class="mike">Mike Jones</p>
    <p>Notorious BIG</p>
</script>
<div class="list"></div>
<script type="text/javascript">
var ArtistList = Backbone.View.extend({
    el: '.list',
    render: function() {
        var markup = _.template($('#artistTemplate').html());
        this.$el.html(markup);
    },
    events: {
        "click p" : "clickParagraph",
        "click .mike" : "clickMikeJones",
        "mouseover p" : "mouseOverEvent"
    }, 
    clickParagraph: function() {
        console.log('You clicked a paragraph element');
    },
    clickMikeJones: function() {
        console.log('You clicked Mike Jones. Who?');
    },
    mouseOverEvent: function() {
        console.log('You moused over a paragraph element');
    }, 		
});
var artistList = new ArtistList();
artistList.render();
</script>
</body>
</html> 

As you can see we have defined a template using the <script type=”text/template” id=”artistTemplate”> and gave it an id. Inside of our render method, we’re using the _.template($(‘#artistTemplate’).html()); to tell Backbone.js which template to use to render our content. In a production application, you’ll likely create lots of different templates.

This might seem like we’ve just moved some code around to do the exact same thing we were doing before, but the real benefit of this will come when you start to add code to insert dynamic data into the template *and* specify a Backbone model for the template to use. This is outside of the scope of this general overview of Backbone views, but it’s still a good idea to show that this is how things are often actually done in a production application.

So that concludes our general survey of Backbone views. We didn’t even actually exhaustively cover everything we possibly could have. There are other methods and properties to take a look at. For more information on Backbone views, you can “view” (heh) the official Backbone.js Views documentation here.

WordPress Themes

Like this post? How about a share?

Stay Updated with the 9bit Studios Newsletter

0 Responses to Backbone.js Views

Leave a Reply