0

I'm new to Backbone and have been testing different ways to filter and render a collection. I'm building a simple todo app. My model looks like this:

{ description: "go for a hike", display: "show" } 

I want to use a search-box to filter my todos based on their "description" property.

As of now, on every 'keyup' I iterate through my collection and see if each model's description includes the value of the search-box. If the model does not include the value of the search-box then I change it's "display" property to "hide", else I keep/change it to "show".

After I've changed the 'display' property on every model instance I then render my collection. The collectionView only renders models whose 'display' property === 'show'

It turn out that this is pretty slow. Can anybody suggest a better way of filtering and rendering a collection on every 'keyup' ?

Here is the filter code:

  filterResults: function() {
    // value respresents the value of the search-box
    var value = this.$el.val();
    todoList.forEach( function (item) {
      if (item.get('description').indexOf(value) > -1) {
        item.set({display: 'show'});
      }else {
        item.set({display: "hide"});
      }
    });
    todoListView.render();
  }

Here is the the CollectionView code:

TodoListView = Backbone.View.extend({
  addOne: function(todoItem) {
    if (todoItem.get('display') === "show") {
      var todoView = new TodoView({model: todoItem});
      todoView.render();
      this.$el.append(todoView.el);
    }
  },
  render: function() {
    this.$el.html("");
    this.collection.forEach(this.addOne, this);
  },

I appreciate the feedback, thanks!

BezR
  • 503
  • 1
  • 6
  • 12
  • A similar question http://stackoverflow.com/questions/18157333/backbone-js-best-practice-for-implementing-instant-search that might help – nikoshr Jun 28 '14 at 16:22

2 Answers2

0

You have two foreach blocs, depending of the size of your collection, it can be a little slow...

Can you call render() when you perform the set on you model? this way you avoid one foreach. maybe you could change how you check if your model have the 'show' property, if you're really focused on performance, try to compare int instead of string.

I advise you to use http://www.datatables.net/, it's avery good plugin and probably will help you.

Hope it Helps.

rcarvalho
  • 790
  • 1
  • 4
  • 14
  • That's a great point and it would definitely speed things up. However, I think that re-rendering on every keyup is what's really slowing things down. I'm wondering if there is a significantly different way of achieving fast filtering and rendering. – BezR Jun 27 '14 at 20:01
  • Yeah, it can also be a problem, take a look on that plugin that I said.. http://www.datatables.net/ Is good – rcarvalho Jun 27 '14 at 20:09
0

I don't think it's a good idea to set a display property and then use it to filter. You can use filter function this way:

var filteredList = todoList.filter(function(item) {
  return item.get('description').indexOf(value) > -1;
});

This will give you the filtered list which you can then send to render function. Also, if your collection size is not huge filtering and rendering should not be a problem. You can always set some minimum length (may be 3) for your filter text.

Niranjan Borawake
  • 1,628
  • 13
  • 20