2014-11-10 5 views
0

Я пытаюсь заставить функцию фильтра работать правильно. Функция принимает массив как параметр. Массив, содержащий все параметры фильтра как int. например, [2,36,11]. Таким образом, int представляют различные параметры фильтра. Тогда я сопоставляю эти элементы массива с другим int, который приходит как переменная. например 2 например. поэтому, если 2 находится в этом массиве, фильтр должен продолжать и делать свою работу.Backbone.js filter

Проблема заключается в том, что эта функция работает только до тех пор, пока значения int в массиве не будут выше 9. Поэтому, если один из параметров фильтра равен 12, это не сработает. Но давайте скажем, что у массива есть int, который равен 1, и вы выбираете опцию фильтра по фильтру 12, он будет считать, что в качестве соответствия и рендеринга нужно отображать, так как indexOf принимает это как совпадение. Как я могу решить это довольно странное поведение?

filter: function(f) { 
    var filter = this.collection.filter(function(o){ 
     var accept = false;          
     $(f).each(function(i,val){ 
      if(_.indexOf(o.get('tags'), val) >-1){ 
       accept = true;      
      } 
     }) 
     return accept; 
    }); 

    var filtered = new PeopleCollection(filter); 
    new PeopleView({ 
     el: this.$('.peoplelist'), 
     collection: filtered 
    }); 
} 
+0

Так что соответствует 12 с 1 или 2, так как 12 содержит это число. Как я могу сделать это как идеальный матч? – user2952238

+0

- это теги '' '' '' '' 'номеров, котор они содержат больше? в чем причина использования 'indexOf', а не прямого сравнения, например' === ' – Quince

+0

Теги - это числа. Похоже, это в моих json '" тегах ":" 9,2,15 "'. Хм, может быть, это было бы решение? Я не совсем понимаю, как написать сравнение. У вас есть пример? – user2952238

ответ

0

Так как метки является строка с числами можно разделить жала на ,, а затем сделать прямую сравнение каждого элемента по отношению к валу.

filter: function(f) { 
    var filter = this.collection.filter(function(o) { 
     var accept = false; 
     $(f).each(function(i, val) { 
      //only run if accept is false 
      if (!accept) { 
       //if tags is a string of numbers spereated by commas 
       //turn that string into array and test each one against the val 
       _.forEach(o.get('tags').split(","), function(tag) { 
        if (accept) { 
         return; 
        } 

        //use parseInt to ensure both are numbers 
        if (parseInt(tag) === parseInt(val)) { 
         accept = true; 
        } 
       }); 
      } 

     }) 
     return accept; 
    }); 

    var filtered = new PeopleCollection(filter); 
    new PeopleView({ 
     el: this.$('.peoplelist'), 
     collection: filtered 
    }); 
} 

здесь быстрая скрипка, используя ту же самую базовую концепцию, только что удалил вид части так откройте консоль, чтобы увидеть результаты каждого фильтра, http://jsfiddle.net/leighking2/gmtvt12p/

+0

Спасибо, сэр! Работает хорошо. – user2952238

0

Это происходит потому, что o.get('tags') возвращается в String, а вы упомянули в комментарии.

Ваше использование _.indexOf(value, item) будет работать с любым значением, имеющим свойство length, и к нему можно получить доступ с помощью записи массива (например, value[0]). Вы можете проверить это, посмотрев на underscore's source code for indexOf function.

Тип JavaScript подходит для этой подписи. Вы на самом деле выполнения вашей функции над каждым характером String:

'1,2,3'.length // 5 
'1,2,3'[0] // '1' 
'1,2,3'[1] // ',' 

Вот почему, когда у вас есть строка «12», он будет соответствовать либо «1» или «2».

Чтобы преобразовать строку в массив чисел, вы можете сделать что-то вроде этого:

'1,2,3'.split(',').map(function(x) { return parseInt(x, 10); }); // [1, 2, 3] 

После этого преобразования, вы можете использовать _.indexOf, как вы ожидаете.

Итак, попробуйте следующее:

filter: function(f) { 
    var filter = this.collection.filter(function(o){ 
     var accept = false;          
     $(f).each(function(i,val){ 
      var tags = o.get('tags').split(',').map(function(x) { // <- 
       return parseInt(x, 10);       // <- 
      });             // <- 
      if(_.indexOf(tags, parseInt(val, 10)) >-1){   // <- 
       accept = true;      
      } 
     }) 
     return accept; 
    }); 

    var filtered = new PeopleCollection(filter); 
    new PeopleView({ 
     el: this.$('.peoplelist'), 
     collection: filtered 
    }); 
}