0

I have a Marionette (2.4.1) CompositeView and when I do a sort it re-renders the entire view rather than the childView. The header icons revert back. I could fix them on render but is there a way that I can just render the childView?

diaryEntries = Backbone.Marionette.CompositeView.extend({
  template  : diaryEntries,
  className: 'diary-entries',
  collection: new Diary(),
  childViewContainer: 'tbody',
  reorderOnSort: true,

  events: {
    'click th[data-sort]': 'sort',
    'click .pagination a': 'paginate'
  },

  initialize: function() {
    this.itemsPerPage = 5;
    this.currentPage = 1;
    this.pages;
  },

  ...

  sort: function(e) {
    var $th, dir, sort, sorted;
    e.preventDefault();
    $th = $(e.currentTarget);
    sort = $th.data('sort');

    if (sort === this.collection.sortField) {
      this.collection.sortDirection *= -1;
    } else {
      this.collection.sortDirection = 1;
    }

    this.collection.sortField = sort;

    $('span.glyphicon').removeClass('active-sort');
    $th.siblings('th').find('span.glyphicon').removeClass('glyphicon-chevron-down glyphicon-chevron-up').addClass('glyphicon-sort');

    if (this.collection.sortDirection === 1) {
      $th.find('span.glyphicon').removeClass('glyphicon-chevron-down glyphicon-sort').addClass('glyphicon-chevron-up active-sort');
    } else {
      $th.find('span.glyphicon').removeClass('glyphicon-chevron-up glyphicon-sort').addClass('glyphicon-chevron-down active-sort');
    }

    this.collection.sort();
  },
...

});
jabbermonkey
  • 1,680
  • 4
  • 19
  • 37

1 Answers1

2

Well, looks like Marionette was concerned about the same thing you are. I couldn't find this in the docs, but it's pretty plain in the source. If you pass this option:

reorderOnSort: true

into your Collection/Composite view, on a 'sort' event the Collection/View will not re render, just its children.

See this line in the Marionette source: https://github.com/marionettejs/backbone.marionette/blob/v2.4.1/src/collection-view.js#L166

UPDATE If you're filtering your children views, running sort on your collection will invoke render on the Collection/CompositeView. The logic is that if you're paginating your children results, then you must sort the original, unfiltered, collection to properly display paginated results.

Nonetheless, I don't see anything intrinsically wrong with paginating a filtered set.

Fortunately, its easy to override the sort method to render whether your results are filtered or not. On you Collection/CompositeView include this method:

reorder: function() {
   var children = this.children;
   var models = this._filteredSortedModels();

   // get the DOM nodes in the same order as the models
   var els = _.map(models, function(model) {
     return children.findByModel(model).el;
   });

   this.triggerMethod('before:reorder');
   this._appendReorderedChildren(els);
   this.triggerMethod('reorder');
   }
},
seebiscuit
  • 4,905
  • 5
  • 31
  • 47