Collection views in backbone js - Learning Backbone js

This entry is part 9 of 14 in the series for A Complete Guide for Learning Backbone Js


Agenda

In the previous lesson, we learned how to use the collection in Backbone js. Now in this topic, we will learn how to generate collection views in Backbone js. Let’s start coding.

What we have till now

So from the previous lesson we have:

  // Person Model
  var Person = Backbone.Model.extend({
      defaults: {
          name: 'Guest User',
          age: 30,
          occupation: 'worker'
      }
  });

  // A List of People
  var PeopleCollection = Backbone.Collection.extend({
      model: Person
  });

  // The View for a Person
  var PersonView = Backbone.View.extend({
      tagName: 'li',

      template: _.template( $('#personTemplate').html()),

      initialize: function(){
          this.render();
      },

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

  var peopleCollection = new PeopleCollection([
      {
          name: 'Mohit Jain',
          age: 26
      },
      {
          name: 'Taroon Tyagi',
          age: 25,
          occupation: 'web designer'
      },
      {
          name: 'Rahul Narang',
          age: 26,
          occupation: 'Java Developer'
      }
  ]);

Three things we need

  • Person Model
  • Person View
  • Person Collection

So we have person model, person view, but the problem is we dont have collection view, a view that collects all smallers view and make it a complete giant view. Lets define one:

Defining a collection

  // View for all people
  var PeopleView = Backbone.View.extend({
      tagName: 'ul'
  });

We defined a PeopleView and as we are using li tag for small view is PersonView that why we defined tagName: ul in PeopleView. Now we need to define a render method which should be these functionalities.

  • Loop over all the person objects
  • Should call render for the person objects
  • Should display a collection as HTML

Defining render method

So lets just define our render method and implement all of the above functionality one by one.

  // View for all people
  var PeopleView = Backbone.View.extend({
      tagName: 'ul',

      render: function(){
      // must do certain things as specified above.
      //Loop over all the person objects
      //Should call render for the person objects
      //Should display a collection as HTML
      }
  });

Let’s create a new object i.e., peopleView and see few things on Chrome developer tools console. I have added initialize function in CollectionView and here is the code for main.js

  // Person Model
  var Person = Backbone.Model.extend({
      defaults: {
          name: 'Guest User',
          age: 30,
          occupation: 'worker'
      }
  });

  // A List of People
  var PeopleCollection = Backbone.Collection.extend({
      model: Person
  });


  // View for all people
  var PeopleView = Backbone.View.extend({
      tagName: 'ul',

      initialize: function(){
          console.log(this.collection);
      },

      render: function(){

      }
  });

  // The View for a Person
  var PersonView = Backbone.View.extend({
      tagName: 'li',

      template: _.template( $('#personTemplate').html()),

      initialize: function(){
          this.render();
      },

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

  var peopleCollection = new PeopleCollection([
      {
          name: 'Mohit Jain',
          age: 26
      },
      {
          name: 'Taroon Tyagi',
          age: 25,
          occupation: 'web designer'
      },
      {
          name: 'Rahul Narang',
          age: 26,
          occupation: 'Java Developer'
      }
  ]);

  // on console

  // var peopleView = new PeopleView({ collection: peopleCollection });

Here is the result from console: collection views in backbone js

  • So what I can see is three objects in the collection view
  • Lots of functions that can be applied to collection views.

So let’s move ahead and use each function and loop over the collection view. Lets for now just run a loop.

  // loop over all the person objects in the peopleCollection
  render: function(){
      this.collection.each(function(person){
              console.log(person);
      });
  }

So first step of looping is done. Now let’s move ahead of the second step i.e., Create a view for each person.

  // loop over all the person objects in the peopleCollection
  render: function(){
      this.collection.each(function(person){
              var personView = new PersonView({ model: person });
              console.log(personView.el);
      });
  }

So far its fine. Now just hold a sec and checkout this carefully. “this” inside the loop lost the reference of the actual collection. Try out these two things to understand it a better way and checkout inline comments.

  // loop over all the person objects in the peopleCollection
  render: function(){
          console.log(this); // reference to collection object.. Pretty useful..
      this.collection.each(function(person){
              var personView = new PersonView({ model: person });

      });
  }

  //OR


  // loop over all the person objects in the peopleCollection
  render: function(){
      this.collection.each(function(person){
              var personView = new PersonView({ model: person });
              console.log(this);  // referencing to global window object and its pretty useless..
      });
  }

So to maintain the reference use this:(checkout inline comments.)

  // loop over all the person objects in the peopleCollection
  render: function(){
      this.collection.each(function(person){
              var personView = new PersonView({ model: person });
              console.log(personView.el);
      }, this);    // at this point we are passing context.. Underscore provides this functionality..
  }

So now we have a reference of original collection view inside the loop. So now just lets complete the third task, i.e., rendering the whole collection list.

  var PeopleView = Backbone.View.extend({
      tagName: 'ul',

      render: function(){
          this.collection.each(function(person){
              var personView = new PersonView({ model: person });
              this.$el.append(personView.el); // adding all the person objects.
          }, this);
      }
  });


  // on console

  //var peopleView = new PeopleView({ collection: peopleCollection });
  //peopleView.render();
  //peopleView.el;

Here is console output:

collection views in backbone js

A quick tip: Always return this from your render method to do chaining. For example person.render.el instead of running two commands person.render and then person.el.

So let’s use this tip finish up the lesson. So currently we have: (checkout inline comments.)

  // Person Model
  var Person = Backbone.Model.extend({
      defaults: {
          name: 'Guest User',
          age: 30,
          occupation: 'worker'
      }
  });

  // A List of People
  var PeopleCollection = Backbone.Collection.extend({
      model: Person
  });


  // View for all people
  var PeopleView = Backbone.View.extend({
      tagName: 'ul',

      render: function(){
          this.collection.each(function(person){
              var personView = new PersonView({ model: person });
              this.$el.append(personView.el);
          }, this);
      }
  });

  // The View for a Person
  var PersonView = Backbone.View.extend({
      tagName: 'li',

      template: _.template($('#personTemplate').html()),

      initialize: function(){
          this.render();
      },

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

  var peopleCollection = new PeopleCollection([
      {
          name: 'Mohit Jain',
          age: 26
      },
      {
          name: 'Taroon Tyagi',
          age: 25,
          occupation: 'web designer'
      },
      {
          name: 'Rahul Narang',
          age: 26,
          occupation: 'Java Developer'
      }
  ]);

Let’s do certain things: (checkout inline comments.)

  • Remove initialize function from PersonView to use chaining and manually call render.
  • Returning this from PersonView render method
  • Returning this from CollectionView render
  • Adding the whole list on Dom for demo purpose.
  // Person Model
  var Person = Backbone.Model.extend({
      defaults: {
          name: 'Guest User',
          age: 30,
          occupation: 'worker'
      }
  });
  // A List of People
  var PeopleCollection = Backbone.Collection.extend({
      model: Person
  });
  // View for all people
  var PeopleView = Backbone.View.extend({
      tagName: 'ul',
      render: function(){
          this.collection.each(function(person){
              var personView = new PersonView({ model: person });
              this.$el.append(personView.render().el); // calling render method manually..
          }, this);
          return this; // returning this for chaining..
      }
  });
  // The View for a Person
  var PersonView = Backbone.View.extend({
      tagName: 'li',
      template: _.template($('#personTemplate').html()),
         //////////   initialize function is gone from there. So we need to call render method manually now..
      render: function(){
          this.$el.html( this.template(this.model.toJSON()));
          return this;  // returning this from render method..
      }
  });
  var peopleCollection = new PeopleCollection([
      {
          name: 'Mohit Jain',
          age: 26
      },
      {
          name: 'Taroon Tyagi',
          age: 25,
          occupation: 'web designer'
      },
      {
          name: 'Rahul Narang',
          age: 26,
          occupation: 'Java Developer'
      }
  ]);
  var peopleView = new PeopleView({ collection: peopleCollection });
  $(document.body).append(peopleView.render().el);   // adding people view in DOM.. Only for demo purpose...

So lets just run this code and see what we have:

Collection views in backbone js

Boom.. A complete list of the person displayed on the page. Pretty nice. ;) So now if you are the thing that so far so much code just to see a list. Hold on. This is how we got the whole structure of the application. Now to add Jquery events all we need to call functions and add some new minor features. Trust me once you start checking out jquery events. You will just fell in love with backbone.


Source code

If you are facing any issues. Check out the source code files at github. I will be creating more and more directories in the same repo regarding each post. Still, if you have any doubts you can comment on the blog post itself, and I will try to reply back asap.