Search code examples
asynchronousbackbone.jscollectionsbackgrid

Backgrid lazily load one column


I'm using Backgrid to create a table. For this I have

Entities.RecipeCollection = Backbone.PageableCollection.extend({
model: Entities.Recipe,
url: '/api/v1/recipes',
state: {
  firstPage: 1
},
queryParams: {
  sort_by : 'id',
  currentPage: 'page',
  pageSize: 'per_page'
},
parseState: function (resp, queryParams, state, options) {
  return {totalRecords: resp.meta.total}
},
parseRecords: function (response, options) {
  return response.results
}

})

and then in my Controller I have

List.Controller = {
   listRecipes: function () {

   $.when(recipeRequest).done(function (recipes) {
     var recipesListView = new List.Pagination({
       collection: recipes
    })

    var columns = [{
      name: id,
      cell: 'String'
    // column 1
   }, {
     // column 2
   }, {
     // column 3 is not available and can only be retrieved by a second
     // call to the server using a different endpoint and with the id from column 1
   }]

   var grid = new Backgrid.Grid({
    columns: columns
    collection: recipes
   })

recipesListLayout.on('show' function () {
    recipesListLayout.show(grid)
   }
  }
}

So where I am stuck is trying to figure out how to update the collection that Backgrid has. I want to do something like

  1. Once the Backgrid has loaded loop through each item in the collection
    1. Issue a request to get the third columns details using the id
    2. On each return from the server update that row and column 3 with the returned data.

If you could point me in the direction of an approach I could take I'd be most appreciative. Most approaches I've seen have suggested making the second call BEFORE the gird is loaded, however I want the user to be able to see the grid even if all fields are not available yet.


Solution

  • You can make a custom cell something like this and use the custom cell while defining the column

    List.Controller = {
       listRecipes: function () {
    
       $.when(recipeRequest).done(function (recipes) {
         var recipesListView = new List.Pagination({
           collection: recipes
       })
    
        Backgrid.CustomCell= Backgrid.Cell.extend({
                className: 'custom-cell',
                events: {
                    'click .some_class': 'doSomething'
                },
                doSomething: function (event) {
                },
                render: function () {
                    var html = "";
                    // make the ajax call with the id from 1st column
                    // you can get the id from this.model.get("id")
                    $.ajax({
                        url: "someurl"
                    })
                      .done(function( data ) {
                        //do something with data
                        // for example 
                        html = "<p class='sth'>" + data.name + "</p>";
                    }).always(function(){
                         this.$el.html(html);
                         this.delegateEvents();
                   });
                   return this;
                }
            });
        }
    
       var columns = [{
          name: id,
          cell: 'String'
            // column 1
       }, {
          // column 2
       }, {
           // and use the custom cell like this
           name: "",
           label: "Custom data from 2nd call",
           editable: false,
           cell: "custom"
      }]
    
       var grid = new Backgrid.Grid({
         columns: columns
         collection: recipes
       })
    
       recipesListLayout.on('show' function () {
          recipesListLayout.show(grid)
       }
     }
    

    }