2013-05-30 3 views
3

У меня есть observableArray, который выглядит примерно так:Фильтрация многомерный Нокаут observableArray с ko.utils.arrayFilter()

this.menuItems = ko.observableArray([ 
    { name: "level1", subItems: [ 
     { name: "level1-1" }, 
     { name: "level1-2" } 
    ] }, 
    { name: "level2" }, 
    { name: "level3", subItems: [ 
     { name: "level3-1" }, 
     { name: "level3-2", subItems: [ 
      { name: "level3-2-1" } 
     ] }, 
    ] }, 
    { name: "level4" } 
]); 

Это визуализирует меню навигации многоуровневый. Таким образом, некоторые элементы могут иметь subItems, другие - нет. И количество уровней неизвестно.

Теперь у меня есть вход для фильтрации, чтобы фильтровать эти вещи.

var self = this, 
    menuFilter = ko.observable(""), 
    filter = menuFilter().toLowerCase(); 

    if (filter === "") { 
     return self.menuItems(); 
    } else { 
     return ko.utils.arrayFilter(self.menuItems(), function (item) { 
      if (item.name.toLowerCase().indexOf(filter) !== -1) { 
       return true; 
      } 
     }); 
    } 

Это прекрасно работает для элементов верхнего уровня, но я не уверен, что лучший путь к петле через self.menuItems().subItems, а затем затем следующий уровень, и следующий, и т.д.

Любые идеи?

Редактировать: Я только что создал этот скрипт JS и, похоже, работает. Теперь я должен выяснить, как это происходит в моем [чуть более сложном] приложении.

http://jsfiddle.net/KSrzL/7/

редактировать (еще раз): Мой последний вопрос в том, что верхний уровень не имеет никакой информации, поэтому я должен начать с .children, который не работает.

http://jsfiddle.net/KSrzL/8/

+1

Является ли точка с запятой в конце строки декларации 'menuFilter' запятой? Вы создаете 'filter' глобальную переменную, которая может быть не такой, какой вы хотите. – bdesham

+0

Хорошая находка. Это была просто опечатка. И это все в объекте namespace'd. Я не использовал некоторые вещи для простоты. – dmathisen

+1

ОК. Какой выход вы хотите от своей функции фильтрации? Вы хотите сохранить иерархическую структуру, чтобы сохранить все предки соответствующих элементов? Или вам нужен ровный список всех совпадений, независимо от того, как они были вложены в исходное дерево? – bdesham

ответ

2

Это похоже на работу: http://jsfiddle.net/MRtRm/

Ключевые фигуры:

self.nonNullItems = function(arr) { 
    return arr.filter(function(x) { return x !== null; }); 
}; 

self.filteredObjectOrNull = function(obj, query) { 
    if (obj.hasOwnProperty('children')) { 
     var filteredChildren = self.nonNullItems(obj.children.filter(function(x) { return self.filteredObjectOrNull(x, query); })); 
     if (filteredChildren.length > 0) 
      return {name: obj.name, children: filteredChildren}; 
    } 

    if (self.matchText(obj.name, query)) 
      return obj; 

    return null; 
}; 

self.filterItems = function() { 
    var filter = self.itemFilter(); 

    if (filter === "") { 
     return self.items(); 
    } else { 
     return self.nonNullItems(self.items().map(function(x) { return self.filteredObjectOrNull(x, filter); })); 
    } 
} 

Я думаю, что это может быть упрощена несколькими способами, но это, кажется, проходит тестирование я сделал , (Вы должны добавить еще несколько уровней меню, чтобы убедиться.)

+0

Ничего себе, мужчина. Это напряжено. И он отлично работает. Одна проблема, с которой я столкнулся, заключается в том, что верхний уровень массива, который я получаю с сервера, пуст, поэтому я должен начать с 'children'. Но когда я это делаю, фильтрация прерывается. Есть идеи по этому поводу? http://jsfiddle.net/MRtRm/4/ – dmathisen

+1

Помните, что 'self.items()' - это массив, содержащий один объект (и этот объект имеет свойство 'children', которое вы хотите). Если вы делаете 'self.items(). Children', вы пытаетесь получить свойство' children' самого массива. Вам нужно посмотреть на первый элемент массива, поэтому: 'self.items() [0] .children'. Если бы я был вами, я бы установил его так, чтобы 'self.items()' дал вам 'self.items() [0] .children' вместо сырого ответа сервера, как сейчас. – bdesham

+0

О, верно! Даже не осознавал этого. Большое спасибо - так помогло! – dmathisen

Смежные вопросы