Chapter 5. Adding and Modifying Elements with Views

In this chapter, we'll take a look at how to do the following:

  • Create new View classes and instances
  • Use Views to render DOM elements
  • Connect Views to Models and Collections
  • Respond to DOM events using Views
  • Decide the rendering style(s) that best fits your project

Views are the core of Backbone-powered sites

While 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
});

Instantiating Views

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:

  • HTML (new Backbone.View ({el: <div id='foo'></div>}))
  • jQuery Selector (new Backbone.View ({el: '#foo'}))
  • DOM element (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 value
  • className: This specifies the HTML class attribute that the element should have
  • id: This specifies the HTML id attribute that the element should have
  • attributes: This specifies the HTML attributes that the element should have

Technically, 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

Rendering view content

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.

Connecting Views to Models and Collections

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.

Accessing a View's el element

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"

A brief aside on $Variable names

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.51.36