2014-01-10 3 views
1

У меня есть модель просмотра, которую я использую для привязки к таблице результатов. Представление динамически отображает таблицу результатов без какого-либо предварительного знания числа или имени столбцов, что отлично. Подобно тому, как описано here, и в интересах сохранения общего, а не специфического для домена, я адаптировал образец кода из этих вопросов.Добавить строку с фильтром в динамически созданную сетку knockout.js

Однако мне нужно добавить строку фильтра, чтобы пользователь мог фильтровать, я добавил строку входов на основе имен столбцов в приведенном ниже коде и попытался связать их с моделью просмотра. Важно, чтобы они были привязаны к модели представления, поэтому, когда я обновляю сетку, модель представления знает о любых применяемых фильтрах.

Я попробовал пару вещей

  • , во-первых, как показано на фрагменте кода ниже я создал наблюдаемый объект фильтра и попытались связать каждое поле в таблице собственности на этот объект фильтра. Это, похоже, не работает.
  • другого варианта я попытался был создать наблюдаемый массив объектов фильтров на основе имен столбцов и связать фильтр столбцы в то, что и не показались работать

Любых мыслей были бы весьма признателен

Большое спасибо, Ed

JS

var VM = function() { 
    var self = this; 
    self.items = ko.observableArray(); 
    self.filters = ko.observable({}); 

    self.columnNames = ko.computed(function() { 
    if (self.items().length === 0) 
     return []; 
    var props = []; 
    var obj = self.items()[0]; 
    for (var name in obj) 
     props.push(name); 
    return props; 


    }); 

}; 
var vm = new VM(); 

ko.applyBindings(vm); 

vm.items.push({ 
    'Name': 'John', 
    'Age': 25 
}); 
vm.items.push({ 
'Name': 'Morgan', 
'Age': 26 
}); 

Вид:

<table> 
    <thead> 
    <tr data-bind="foreach: columnNames"> 
     <th> <span data-bind="text: $data"></span> 

     </th> 
    </tr> 
    </thead> 
    <tbody > 

    <!-- add filter rows --> 
    <tr data-bind="foreach: $root.columnNames"> 
     <td ><input type='text' data-bind="value: $root.filters[$data]"/></td> 
    </tr> 
    <!-- add the items --> 
    <!-- ko foreach: items --> 
    <tr data-bind="foreach: $parent.columnNames"> 
     <td data-bind="text: $parent[$data]"></td> 
    </tr> 
    <!-- /ko --> 
    </tbody> 
</table> 

ответ

4

Я сделал скрипку, в которой filters хранится в объекте {Col1 : Value1, Col2 : Value2...}.

Теперь вычисленный columnNames возвращает объект, содержащий как заголовок столбца, так и его фильтр.

Я также создал вычисляемый фильтр, который содержит только элементы, которые соответствуют фильтрам.

массив subscriptions предназначен для отслеживания подписки, чтобы удалить их при изменении количества столбцов.

var VM = function() { 
    var self = this; 
    self.items = ko.observableArray(); 
    self.filters = ko.observable({}); 
    self.filteredItems = ko.computed(function() { 
     var filters = self.filters(); 

     var items = ko.utils.arrayFilter(self.items(), function (item) { 
      for (var col in filters) { 
       var v = (item[col] || '').toString(); // cell value 
       var f = filters[col]; // what you typed in header 
       if (v.indexOf(f) < 0) return false; // filter is contains 
      } 
      return true; 
     }); 
     return items; 
    }); 
    var subscriptions = []; 
    self.columnNames = ko.computed(function() { 
     // clean old subscriptions 
     ko.utils.arrayForEach(subscriptions, function (s) { s.dispose(); }); 
     subscriptions = []; 
     if (self.items().length === 0) return []; 
     var props = []; 
     var obj = self.items()[0]; 
     for (var name in obj) {   
      var p = { name: name, filter: ko.observable('') }; 
      // subscribe : so when you type something, filterOnChanged will be invoked. 
      subscriptions.push(p.filter.subscribe(filterOnChanged, p)); 
      props.push(p); 
     } 
     return props; 
    }); 

    var filterOnChanged = function (value) { 
     console.log([this.name, value]); 
     var filters = self.filters(); 
     filters[this.name] = value; 
     self.filters(filters); 
    }; 

}; 

See fiddle

+0

Привет Damien, спасибо за такой быстрый ответ. Мне нравится решение, и оно отлично работает, но очень медленно при работе с большим количеством строк, я предполагаю, что каждый раз, когда добавляется строка, все подписки удаляются и воссоздаются, а также мои фильтры передаются на сервер, а не фильтрация локального списка. Я изменил так, что columnNames - это компьютер из нового наблюдаемого firstRow, который заполняется только тогда, когда исходные данные загружаются и не обновляются при фильтрации данных. – Mingo

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