Backbone.View Patterns – How & Why Use Subviews

September 10, 2012, Oren Farhi

IMG_20120910_110740_Anne_Dirt

Backbone.View is a very useful javascript class when it comes to rendering data and attach a behavior to DOM elements. Today, I cannot imagine front end javascript code without some kind of a view class.
Often, I tend to keep my views as small as possible. Sometimes it is hard to determine what is a view and how to break big chunk of data to smaller views. In this post I want to point out some useful cases where it is beneficial to use “sub-views” and the benefits of such methodology.

How to Identify the need for a sub view

In a recent post, I explained the relationship between Backbone’s Model and View.
When a model has an array of similar items, where each has some sort of interaction – it is a good practice to render each item as a sub – view. Using a separate view for each item gives the option to control the behavior attached to each – usually, on click I am able to get a reference to the correct model of that specific item rather than trying to get the id of the source element and start querying to DOM.
In example, take this blog post’s commenting list. If I were to define it using backbone, the Model would be:

Identifying that each comment is a separate module will result in a much cleaner, modular and error free code.

Why using sub views is good?

  1. If a view of a comment has several events – attaching these events is self contained inside of every view:
  2. A comment might be a media comment – an audio or a video. In this case, if the comment model has an attribute of ‘type’, it is easy for the comments panel view to create an appropriate view:
  3. This method of code organization promotes developing reusable and loosely coupled modules.

How to manage sub views

Managing sub views with Backbone should take in consideration few issues.
Sub view is eventually a javascript object – so, there’s a need to avoid possible memory leaks.
The main view which holds the sub views should dismiss the views when rendering new ones or whenever the main view is dismissed.
One best practice is saving sub views in a property as such:

This is one way of managing sub views. It’s important to note that each sub view can have its own sub views – so, the code above can be used as a somewhat boilerplate for views that have sub views – no matter the hierarchy level.

  • me

    like!!!

  • opensas

    It would be great if you could include the code of the destroy method. There’s a lot of disussion about the best way to remove a view. This is a very good article: http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/, and a related question on stack overflow: http://stackoverflow.com/questions/6569704/destroy-or-remove-a-view-in-backbone-js

  • Me

    “Why to use”??

  • http://www.orizens.com/ Oren Farchi

    Hi opensas.
    There are quite good examples on the both links you shared.However, If one is working correctly with a distinct separation between Models and View or DOM and JS data, then a ‘destroy’ method of a View should:- unbind event listeners on this.$el
    - remove DOM element from DOM (build in as ‘remove’ method by jquery)
    - run ‘destroy’ for sub views :-)- remove references of sub views – in this post – ‘this.views’ should be referenced to null. You can also use js ‘delete’ to explicitly free js memory for views.As a rule of thumb, you should clean any references to objects in side your View object plus the reference to the view itself – which will apparently be somewhere in your code.

  • opensas

    I’d like something fairly simple and bullet proof… do you think something like this might work??? (haven’t tried it)

    http://jsfiddle.net/opensas/DcZdq/

    saludos

    sas

  • http://www.orizens.com/ Oren Farchi

    Hi Sas.
    Change this line:
    this.views = [];
    to a property of the object:
    views: [];
    Otherwise – that code should work as expected.

  • opensas

    silly mistake, thanks
    this is the corrected version: http://jsfiddle.net/opensas/DcZdq/5/

  • Pingback: Backbone.View Patterns – rendering a collection « Orizen Designs – Oren Farhi – Javascript Blog, Backbone Blog, HTML5, CSS3

  • roblevintennis

    Yeah figuring out a good mechanism for view disposal is challenging. We founds that an additional trouble spot is not inadvertently staying around if attached to jQuery plugins custom events, etc. It seems that boiler plate unwinding should be done by a super or mixin, but also optionally overridden by each view itself to ensure these custom events are completely unbound.

  • http://www.orizens.com/ Oren Farhi

    jquery plugins should be considered as 3rd party that should be handled separately in the destroy process.

    My advice is using a “destroy” event (or “before:destroy”) so you can listen to and unbind any 3rd party attachments.

    Thanks.

  • johndurbinn

    Sammy Farha!

  • johndurbinn

    Backbone == LOTS of BOILERPLATES!!!

  • UncleBob

    Two things; first, you could use map() to create your views list:

    this.views = this.collection.map(function(item) {
    return new CommentView({ model: item });
    });

    Also, for performance purpose it may be wise to update DOM rendering only once, still using map():

    this.$el.html(this.views.map(function(view) {
    return view.render().$el;
    }));

    (untested code, but you get the picture)

  • http://www.orizens.com/ Oren Farhi

    hi.
    You’re right – “map” for creating and appending views is much more cleaner method for creating views (updated the code).
    Thanks :)

  • miphe

    Very interesting, thanks for the example. As a bare boilerplate looks good, I would prefer to use Marionette and perhaps by BossviewBossview for bigger projects.

  • http://www.orizens.com/ Oren Farhi

    hi miphe.

    thanks for your comment.

    i integrated the idea of dealing with views to 2 plugins:

    backbone collection view – https://github.com/orizens/backbone.collection-view

    backbone switcher – https://github.com/orizens/backbone-switcher