Understanding view in Backbone.js

A view in backbone.js represents a DOM element, as well as the child elements within that element.Backbone views are used to reflect applications’ data models front-end. They are also used to listen to events and react accordingly.Backbone views are almost more convention than they are code.They don’t determine anything about HTML or CSS,it can be used with any JavaScript template library. The general idea is to organize interface into logical views, backed by models.

In the following we can see the relationship of view and other components of backbone:

view

Extend:
we can extend the views with Backbone.View.extend(properties, [classProperties]). we can also create a custom view class.a custom view class will override the render function, specify declarative events,the tagName, className, or id of the View’s root element.Properties like tagName, id, className, el, and events may also be defined as a function.

var Document = Backbone.View.extend({
  tagName: "li",
  className: "document",
  events: {
    "click .icon":          "open",
    "click .button.edit":   "openEditDialog",
    "click .button.delete": "destroy"
  },
  initialize: function() {
    this.listenTo(this.model, "change", this.render);
  },
  render: function() {
   ...
  }
});

Constructor / initialize:
We can initialize a view using new View ([options]) .if we pass properties like model, collection, el, id, className, tagName, attributes and events through the view.those properties will be attached directly to the view. If the view defines an initialize function, it will be called when the view is first created.

var doc = documents.first();
new Document({
  model: doc,
  id: "document" + doc.id
});

el:
we have seen that there are some properties in view which can be used like functions. this feature is very useful. if we can have a property which is used as a function, can give us an empty div to work with. we can also render the views anytime we want through this property.All views have a DOM element at all times. whether they’ve already been inserted into the page or not.

var Document = Backbone.View.extend({
  tagName: 'li'
});
var Person = Backbone.View.extend({
  el: 'body'
});
var doc = new Document();
var per = new Person();
alert(doc.el + ' ' + per.el);

$el:
This property is a cached jQuery object for the view’s element. A reference instead of re-wrapping the DOM element all the time.

view.$el.show();
listView.$el.append(itemView.el);

setElement:
when we will apply a Backbone view to a different DOM element, we need to use setElement, to create the cached $el reference and move the view’s delegated events from the old element to the new one.to reach this goal we can use view.setElement(element).

initialize: function(){ 
  this.setElement( this.el );
  this.render();
}

Template:
In view we can also use templates. But template for a view isn’t a function provided directly by Backbone.Though it is well known to define a template function on views. In this way, when rendering the view, we should have convenient access to instance data.

var Library = Backbone.View.extend({
  template: _.template(...)
});

Render:
rendering is one of the most useful methods in view. But it also produces some problems. we can use view.render(). Without this there are many methods which we can rely on.So,before we start evaluating different methods for rendering we should have some requirements remembered:
1. Render should be able to be called multiple times without side effects.
2. The order of the DOM should be declared in templates, not JavaScript.
3. Calling render again should maintain the state the view was in.
4. Rendering twice shouldn’t trash views just to re-construct them again.
With those requirements in mind,let us discuss about some methods:
To meet the above requirements we should make sure that delegateEvents is called to rebind the events on sub views any time .html() runs. And since Backbone’s setElement calls delegateEvents already, it could look like this:

render : function () {
    this.$el.$html(this.template());

    this.subview.setElement(this.$('.subview')).render();
    this.anotherSubview.setElement(this.$('.another-subview')).render();
    return this;
}

Because it is a little hard in case of parsing we thought that we could use a helper method called help which we should define in our BaseView and our typical render method looks something like this:

render : function () {
    this.$el.html(this.template());

    this.help(this.subview,        '.subview');
    this.help(this.anotherSubview, '.another-subview');
    return this;
}

help is basically just setElement—which calls delegateEvents for. But with a nicer API and an automatic call to render:

help : function (view, selector) {
    view.setElement(this.$(selector)).render();
}

With help, those lines in render supports the conditions above mention. but as we mentioned before there are many methods for rendering. It is just one of them.

remove:
There will be many times we want to delete a specific view for many reasons. We can try to use the view.remove() to accomplish that task. But view always stays bound to many methods. so view.remove() not only deletes a view but removes a view from the DOM, and calls stopListening to remove any bound events that the view has listen to.

updateView: function() {
  view.remove();
  view.render();
};

delegateEvents:
In the render() we have used delegateEvents. But we did not explained it. In this portion we will try to understand about this event. This event uses jQuery’s on function to provide declarative callbacks for DOM events within a view. If an events hash is not passed directly, uses this.events as the source. Events are written in the format {“event selector”: “callback”}. The callback may be either the name of a method on the view, or a direct function body. Without the selector we know that the event to be bound to the view’s root element (this.el). To make it easier to programmatically the events property define events and inherit them from parent views.
Using delegateEvents provides a number of advantages over manually using jQuery to bind events to child elements during render. All attached callbacks are bound to the view before being handed off to jQuery, so when the callbacks are invoked, this continues to refer to the view object. When delegateEvents is run again, all callbacks are removed and delegated fresh. It is very useful for views which need to behave differently when in different modes. we also should remember this that although delegateEvents is a custom event it can also be called within the View’s constructor by default. A view that displays a document in a search result might look something like this:

var Document = Backbone.View.extend({
  events: {
    "dblclick"                : "open",
    "click .icon.doc"         : "select",
    "contextmenu .icon.doc"   : "showMenu",
    "mouseover .title .date"  : "showTooltip"
  },
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  },

  open: function() {
    window.open(this.model.get("viewer_url"));
  },
  select: function() {
    this.model.set({selected: true});
  },
});

undelegateEvents:
Many times we will feel the need to disable a specific view from the DOM temporarily. We can achieve this by using undelegateEvents() .This event removes all of the view’s delegated events. This method is a custom method in backbone.
The Backbone.View constructor calls delegateEvents automatically. But undelegateEvents does not get called when we remove the view with Backbone.View.prototype.remove.To achieve this we have to override the remove() view method with this code:

Backbone.View.prototype.remove = function() {
    var remove = Backbone.View.prototype.remove;

    if (this.undelegateEvents) {
      this.undelegateEvents();
    }
    return remove.apply(this, arguments);
};

conclusion:
In the above article we have try to discuss about the views in backbone.Though we have seen many perspective of views in the above article. There could be many other ways to work with view. So, it would be better if you are willing to join with us in this discussion and place your opinion.

Some related articles :

1>Introduction to Backbone.js

2>Models in Backbone.js

3>Underscore Methods in Backbone.js

4>Backbone Routes and History

5>Collections in Backbone.js

6>Templates In Backbone.js

7>WHY SHOULD WE USE SERVER SIDE IN BACKBONE.JS?

8>Backbone.js at a glance
We will have other detail of Backbone features in our later articles. So please look for the same.
If you find this article helpful, you can connect us in Google+ and Twitter.