Search code examples
javascriptjquerybackbone.jsunderscore.js

Backbone sort collections by click on non template elements


I want to sort my backbone collections by clicking non backbone template elements

In brief , i have 2 Sorting options named "Sort by date" and "Sort by name". when i click these elements i need to sort my collection in my backbone view

View template :

    <ul>
    <li>Sort By date</li>
    <li>Sort By name</li>
    </ul>

    <script type="foo/bar" id='videos-thumbnail'>
          <div class="col-md-4">
          <div class="video-thumbnail-item">
            <div style="background-image:url(recenty_added/recentlyadded2.jpg);" class="video-thumbnail"> </div>
            <div class="video-details">
              <div class="video-title text-purple uppercase"><%= title %></div>
              <div class="video-date"><%= date %></div>
            </div>
            <div class="video-thumbnail-checkbox"> <span class="custom-checkbox">
              <input type="checkbox" class="playlist-checkbox" name="addto-playlist[]">
              </span>
              <% if (is_rights_managed== true) { %>
              <div class="checkbox-label-light">RM</div>
              <% } else {%>
              <div class="checkbox-label-light"></div>
              <% } %>
            </div>
            <div class="video-thumbnail-options"> <span title="Download" class="option-parts"> <i class="fa fa-download"></i> </span> <span title="Edit" class="option-parts"> <i class="fa fa-pencil"></i> </span> <span title="More Information" class="option-parts"> <i class="fa fa-info-circle"></i> </span> <span title="View Details" class="option-parts"> <i class="fa fa-search"></i> </span> <span title="Add to Clipbins" class="option-parts"> <i class="fa fa-folder-open"></i> </span> <span title="Add to Cart" class="option-parts"> <i class="fa fa-cart-plus"></i> </span> <span title="Contact me about this Clip" class="option-parts"> <i class="fa fa-envelope"></i> </span> </div>
          </div>
        </div>
    </script> 

<div class="row" id="thumbnail_target"> </div>

App :

//backbone & underscore
$(function() {
var Videos = Backbone.Model.extend();

var VideoList = Backbone.Collection.extend({
   model: Videos,
   url: 'https://api.myjson.com/bins/4mht3'
});

var videos = new VideoList();

var VideoView = Backbone.View.extend({
   el: "#thumbnail_target",
   template: _.template($('#videos-thumbnail').html()),
   render: function(eventName) {
      _.each(this.model.models, function(video){
         var videoTemplate = this.template(video.toJSON());
         $(this.el).append(videoTemplate);
      }, this);
      return this;
   },
});

var videosView = new VideoView({model: videos});

videos.fetch({
    success: function() {
        videosView.render();
        videoslistView.render();
    }
});

});

Am newbie to backbone and underscore, am not sure how to make this work

Example fiddle : Fiddle


Solution

  • Since you have access to collection outside view, you can simply use jquery to bind an event handler for the <li>, which updates the collections comparator and sorts it. Then have the view re-render itself when a sort event occurs on the collection.

    for the demo I'm using string and number types of sort attributes so that I can directly set it as comparator. You should write a custom comparator function that handles sorting based on different types of arguments like string, number, date etc. Updated fiddle

    //backbone & underscore
    $(function() {
      var Videos = Backbone.Model.extend();
      var VideoList = Backbone.Collection.extend({
        model: Videos,
        url: 'https://api.myjson.com/bins/4mht3'
      });
      var videos = new VideoList();
      var VideoListView = Backbone.View.extend({
        el: "#thumbnail_target",
        template: _.template($('#videos-thumbnail').html()),
        initialize: function() {
          this.listenTo(this.collection, 'sort', this.render);
        },
        render: function(eventName) {
          this.$el.empty();
          _.each(this.collection.models, function(video) {
            var videoTemplate = this.template(video.toJSON());
            this.$el.append(videoTemplate);
          }, this);
          return this;
        },
      });
      var videosView = new VideoListView({
        collection: videos
      });
      videos.fetch({
        success: function(collection) {
          videosView.render();
        }
      });
      $('#sortBy').on('click', 'li', function() {
        var category = $(this).text().split('Sort By ')[1];
        videos.comparator = category;
        videos.sort();
      });
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
    <ul id="sortBy">
      <li>Sort By average</li>
      <li>Sort By title</li>
    </ul>
    <script type="foo/bar" id='videos-thumbnail'>
      <div class="col-md-4">
        <div class="video-thumbnail-item">
          <div style="background-image:url(recenty_added/recentlyadded2.jpg);" class="video-thumbnail"></div>
          <div class="video-details">
            <div class="video-title text-purple uppercase">
              <%=t itle %>
            </div>
            <div class="video-date">
              <%=d ate %>
            </div>
          </div>
          <div class="video-thumbnail-checkbox"> <span class="custom-checkbox">
              <input type="checkbox" class="playlist-checkbox" name="addto-playlist[]">
              </span>
            <% if (is_rights_managed==t rue) { %>
              <div class="checkbox-label-light">RM</div>
              <% } else {%>
                <div class="checkbox-label-light"></div>
                <% } %>
          </div>
          <div class="video-thumbnail-options"> <span title="Download" class="option-parts"> <i class="fa fa-download"></i> </span>  <span title="Edit" class="option-parts"> <i class="fa fa-pencil"></i> </span>  <span title="More Information" class="option-parts"> <i class="fa fa-info-circle"></i> </span> 
            <span
            title="View Details" class="option-parts"> <i class="fa fa-search"></i> 
              </span> <span title="Add to Clipbins" class="option-parts"> <i class="fa fa-folder-open"></i> </span>  <span title="Add to Cart" class="option-parts"> <i class="fa fa-cart-plus"></i> </span>  <span title="Contact me about this Clip" class="option-parts"> <i class="fa fa-envelope"></i> </span> 
          </div>
        </div>
      </div>
    </script>
    
    <div class="row" id="thumbnail_target"></div>