In this chapter, we'll take a look at how to do the following:
View
classes and instancesWhile data is certainly important in any application, you can't have an application without a user interface at all. On the web, this means that you have a combination of DOM elements (to display information to the user) and event handlers (to receive input from the user). In Backbone, both of these things are managed by Views; in fact, it's only fair to say that Views pretty much control all the input and output on a Backbone-powered site.
Just as Models wrap an attributes
object and Collections wrap a models
array, Views
wrap a DOM element inside a property called el
. Unlike attributes and models, however, el
is not hidden, and Backbone doesn't watch it for changes, so there's nothing wrong with referencing a View's el
directly:
someModel.attributes.foo = 'bar'; // don't do this $('#foo').append(someView.el); // feel free to do this
To create a new View
subclass, simply extend Backbone.View
in the same way as you created new Model
and Collection
subclasses, as shown here:
var MyView = Backbone.View.extend({ // instance properties and methods of MyView go here }, { // static properties and methods of MyView go here });
As we mentioned in Chapter 2, Object-oriented JavaScript with Backbone Classes, Views take only a single options
argument when instantiated. The most important part of these options is the el
property, which defines the DOM element that the View will wrap as its el
. A View's el
option can be defined in one of the following three ways:
new Backbone.View ({el: <div id='foo'></div>})
)new Backbone.View ({el: '#foo'})
)new Backbone.View ({el: document.getElementById('foo')})
)You can also choose not to provide an el
option, in which case Backbone will create the View's el
option for you. By default, Backbone will simply create an empty DIV
element (<div></div>
), although you can change this by providing other options when you create your view. You can provide the following options:
tagName
: This changes the generated elements' tag from div
to the specified valueclassName
: This specifies the HTML class
attribute that the element should haveid
: This specifies the HTML id
attribute that the element should haveattributes
: This specifies the HTML attributes that the element should haveTechnically, you can specify both the class and ID of a View's element using the attributes
option, but because they are important to the definition of a View, Backbone provides separate id
and className
options.
Instead of defining the preceding options when you instantiate your View, you can also choose to define them in a View
class. For instance, if you want to create a View
class that generates a <form>
element with a class of nifty
, you should do the following:
var NiftyFormView = Backbone.View.extend({ className: 'nifty', tagName: 'form' }); var niftyFormView = new NiftyFormView(); var niftyFormView2 = new Backbone.View({ className: 'nifty', tagName: 'form'}); // niftyFormView and niftyFormView2 have identical "el" properties
While Views can take an el
option to define their initial element, it is rare for them to leave this el
option unchanged. For instance, a list
View might take an <ul>
element as its el
option but then fill this list with the <li>
elements (possibly using data from a Collection). In Backbone, this generation of inner HTML is done inside the View's render
method.
However, when you try to use the render
method of an unmodified View, you quickly notice a problem with Backbone's default implementation, as follows:
render: function() { return this; }
As you can see, the default render
method doesn't actually render anything. This is because different Views can have entirely different content, so it doesn't make sense for Backbone to provide only one way of generating that content. Instead, Backbone leaves the implementation of your View's render
method entirely up to you.
Later on, in this chapter, we'll consider the various strategies for how you might want to implement render
methods on your site, but before we get to that, let's first examine how to connect Models and Collections to Views as well as how Views handle event bindings.
When a View is created, it can take two important options: Model
and Collection
. Both of these options are simple property options, which is to say that Backbone doesn't actually do anything with them other than add them as properties to the View. Even so, these properties can be very useful when you want to display or edit data that you've previously generated. For instance, if you want to associate a View with a book
Model that you have created, you can do the following:
var book = new Backbone.Model({ title: 'Another Fake Title? Why?' }); var bookView = new Backbone.View({model: book}); // book == bookView.model;
When you write the render
method for your book
View, you can use that Model in order to get the data to generate the appropriate HTML. For instance, here's a simple implementation of render
, loosely borrowed from the Backbone documentation:
render: function() { this.$el.html(this.template(this.model.toJSON())); return this; }
As you can see, the imaginary render
method passes the output of the Model's toJSON
to the View's templating system, presumably so that the templating system can use the Model's attributes to render the View.
Once you've created a View, you can access the element that it wraps at any time by referring to its el
property. You can also access a jQuery-wrapped version of the same element by referring to the View's $el
property. Take an example of the following code:
var formView = new Backbone.View({tagName: 'form'}); formView.$el.is('form'), // returns true
Backbone also provides another convenient shortcut when you want to access elements inside a View's element: the $
method. When you use this method, it's effectively the same as calling jQuery's find
method from the View's element. Because the search for the element is localized to only look through the View's el
element and not through the entire page's DOM, it will perform much better than a global jQuery selection.
For example, if you create a View of a <form>
element with an <input>
element inside it, you can use the View's $
method to access the <input>
element , as shown here:
var formView = new Backbone.View({ el: '<form><input value="foo" /></form>' }); var $input = formView.$('input'), $input.val(); // == "foo"
When working with jQuery objects in Backbone (or even just in JavaScript, in general), it may often be difficult to tell whether a given variable refers to a View
element or to its el
element. In order to avoid confusion, many programmers (including the authors of both Backbone and jQuery) preface any variable that points to a jQuery object with the $
symbol, as follows:
var fooForm = new Backbone.View({id: 'foo', tagName: 'form'}); var $fooForm = fooForm.$el;
While this practice is certainly not necessary to use Backbone, adopting it will likely save you from confusion in the future.
13.58.51.36