Backbone.View Patterns – How & Why Use Subviews

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//- considering there's an object with comments data

varCommentsPanel={

postId:44321,

otherData:{/**/}

comments:[

{id:1234,content:"some content",collapsed:true,name:"oren"}

{id:4321,content:"some other",collapsed:true,name:"bill"}

]

}

//- a comment model that can be created from above

varComment=Backbone.Model.extend({

defaults:{

content:"",

collapsed:true,

thumb:'url-to-user-thumb.png',

name:'user-name',

date:'date-published',

liked:false

}

});

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?

If a view of a comment has several events – attaching these events is self contained inside of every view:

1

2

3

4

5

6

7

8

9

10

11

12

13

varCommentView=Backbone.View.extend({

events:{

'click .collapse':'toggle',

'click .reply':'reply'

},

collapse:function(){

//- 'this' is still the same context of this View

this.trigger('comment-toggled',this.get('id'))

}

});

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:

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

varCommentsPanelView=Backbone.View.extend({

initialize:function(){

//- set views placeholder

this.views=[];

},

render:function(){

//- clean views before rendering new ones

this.destroyViews();

//- create new views

this.views=this.collection.map(this.createView,this);

this.$el.append(_.map(this.views,this.getDom,this));

},

createView:function(model){

returnnewCommentView({model:model});

},

getDom:function(view){

returnview.render().el;

},

destroyViews:function(){

//- call destroy method for each view

_.invoke(this.views,'destroy');

this.views.length=0;

}

});

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.