2016-02-01 3 views
0

Я новичок в Knockout. Я успешно извлекаю данные, но пытаюсь отфильтровать их на основе активной или неактивной записи. Когда я это делаю, он передает правильные значения, но мой наблюдаемый массив пуст.Нокаут JS ObservableArray потеряет значения

Я заполняю его ajax. Мое понимание заключается в том, что я заполняю наблюдаемый массив и не нужно делать никаких других обращений к серверу, если я не хочу писать в базу данных или получать новые данные. Поэтому, когда этот наблюдаемый массив имеет данные, я должен иметь возможность фильтровать его, не ударяя базу данных снова. Кажется, это не работает для меня. Я думаю, что я делаю что-то неправильно. Мысли?

Вот код:

var sgsoip = window.sgsoip || {}; 
 
sgsoip.FunctionalAreaViewModel = function (ko, db) { 
 
    //'use strict'; 
 
    var self = this; 
 
    self.functionalAreas = ko.observableArray([]) 
 

 
    self.headers = [ 
 
     { title: '', sortPropertyName: '', asc: true }, 
 
     { title: 'Functional Area Name', sortPropertyName: 'FunctionalAreaName', asc: true }, 
 
     { title: 'Active', sortPropertyName: 'FunctionalAreaActive', asc: true } 
 
    ]; 
 
    self.filters = [ 
 
     { title: "Show All", filter: null }, 
 
     { title: "Active", filter: function (item) { return item.FunctionalAreaActive == 'true'; } }, 
 
     { title: "Inactive", filter: function (item) { return item.FunctionalAreaActive == 'false'; } } 
 
    ]; 
 

 
    self.activeFilter = ko.observable(self.filters[0].filter); 
 

 
    self.setActiveFilter = function (model, event) { 
 
     self.activeFilter(model.filter); 
 
    } 
 

 
    self.filteredItems = ko.computed(function() { 
 
     if (self.activeFilter()) { 
 
      return ko.utils.arrayFilter(self.functionalAreas, self.activeFilter()); //When hitting filter self.functionalAreas is empty 
 
     } else { 
 
      return self.functionalAreas(); //this works as expected 
 
     } 
 
    }); 
 

 
    self.activeSort = self.headers[1]; 
 
    function _init() { 
 
     db.getFunctionalAreas(function (data) { 
 
      //var a = []; 
 
      ko.utils.arrayForEach(data || [], function (item) { 
 
       self.functionalAreas.push(new sgsoip.FunctionalArea(item.FunctionalAreaID, item.FunctionalAreaName, item.FunctionalAreaActive)); 
 
      }); 
 
      //self.functionalAreas(a); 
 
     }); 
 
    } 
 
    
 
    _init(); 
 
    return { 
 
     functionalAreas: functionalAreas, 
 
     sortedFunctionalAreas: sortedFunctionalAreas, 
 
     removeFunctionalArea: removeFunctionalArea 
 
    }; 
 
}(ko, sgsoip.DataContext);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> 
 
<div class="btn-group" data-bind="foreach: filters"> 
 
     <button class="btn btn-small" data-bind="click: setActiveFilter, text: title"></button> 
 
    </div> 
 

 
    <table class="table" id="gridoutput"> 
 
     <thead> 
 
      <tr data-bind="foreach: headers"> 
 
       <th><a href="#" data-bind="click: filteredItems, text: title"></a></th> 
 
      </tr> 
 
     </thead> 
 
     <tbody data-bind="foreach: filteredItems"> 
 
      <tr> 
 
       <td><a href="javascript:void(0);" data-bind="click: removeFunctionalArea" title="Delete"><i class="icon icon-trash"></i></a></td> 
 
       <td data-bind="text: FunctionalAreaName"></td> 
 
       <td data-bind="text: FunctionalAreaActive"></td> 
 
      </tr> 
 
     </tbody> 
 
    </table>

Edit - Добавлены некоторые недостающий материал для тех, кто спрашивает.

var sgsoip = window.sgsoip || {}; 
 
sgsoip.DataContext = (function ($) { 
 
    'use strict'; 
 
    var me = { 
 
     getFunctionalAreas: getFunctionalAreas, 
 
     removeFunctionalArea: removeFunctionalArea, 
 
     saveFunctionalArea: saveFunctionalArea 
 
    }; 
 
    function getFunctionalAreas(callback) { 
 
     var functionalareas = null; 
 
     if ($.isFunction(callback)) { 
 
      //functionalareas = localStorage["functionalareas"]; 
 
      //alert('test'); 
 

 
      //if (functionalareas != "undefined") { 
 
      // callback(functionalareas); 
 
      //} else { 
 
      $.getJSON('/FunctionalAreas/GetJsonData', function (data) { 
 
        //localStorage["functionalareas"] = JSON.stringify(data.FunctionalAreas); 
 
       callback(data); 
 
       }); 
 
      //} 
 
     } 
 
    } 
 

 
    function removeFunctionalArea(functionalArea) { 
 

 
    } 
 

 
    function saveFunctionalArea(functionalArea) { 
 

 
    } 
 
    return me; 
 
})(jQuery); 
 

 

 
var sgsoip = window.sgsoip || {}; 
 
sgsoip.FunctionalArea = function (FunctionalAreaID, FunctionalAreaName, FunctionalAreaActive) { 
 
    'use strict'; 
 
    this.FunctionalAreaID = ko.observable(FunctionalAreaID); 
 
    this.FunctionalAreaName = ko.observable(FunctionalAreaName).extend({ required: "Functional Area Name is required" }); 
 
    this.FunctionalAreaActive = ko.observable(FunctionalAreaActive).extend({ required: "Active is required" }); 
 
    this.HasError = ko.pureComputed(function() { 
 
     return this.FunctionalAreaActive.hasError() || this.FunctionalAreaName.hasError(); 
 
    }, this); 
 
};

EDIT Похоже, я могу добавить больше разъяснений. Это не потеряет данные. Я прошел весь путь через код нокаута. И он проходит через наблюдаемые для сравнения.

я получаю следующий кусок кода:

arrayFilter: function (array, predicate) { 
 
      array = array || []; 
 
      var result = []; 
 
      for (var i = 0, j = array.length; i < j; i++) 
 
       if (predicate(array[i], i)) 
 
        result.push(array[i]); 
 
      return result; 
 
     },

И он никогда не выполняет result.push (массив [я]) линии.

+0

ваш образец не определяет 'db' или' FunctionalArea'; Я пытаюсь проверить это на скрипке. можете ли вы предоставить самостоятельный рабочий пример? – dfperry

+0

В какой-то степени я могу. Но вам придется заменить мой json-вызов статическим json, я думаю. Одну секунду. Я обновлю сообщение. –

+0

он даже не должен быть вызовом ajax, просто включите данные и установите его в методе _init – dfperry

ответ

1

При переборе или любом другим способа, работая с наблюдаемым массивом, вы должны помнить, чтобы добавить скобку в конце, например, так:

return ko.utils.arrayFilter(self.functionalAreas(), self.activeFilter()); 

Это только при использовании методов, которые фактически осуществлены на observableArray (например, push, remove и т. д.), что вы можете оставить круглые скобки.

+0

Я так и думал, хотя в приведенном ниже примере не было этого: http://ryanrahlf.com/filtering-table-data-with-knockout-js/ Я внес изменения и по-прежнему получаю тот же результат. Как будто любое действие после начальной загрузки страницы очищает Observablearray. –

+0

Через несколько дней.Это оказалось правильным, но немного отличается от комментария. Это привело к правильному ответу. Несмотря на множество примеров, показывающих эту работу без() онлайн, это не сработало для меня. Я использую нокаут-3.4.0. Проблема была в моем массиве self.filters, я не использовал() в этой строке - return item.FunctionalAreaActive() === true; и это привело к его провалу. –

+0

На самом деле, вчера я смотрел презентацию Джона Папы о нокауте на YouTube, и он специально сказал, что нокаут достаточно умен, чтобы понять, когда свойство не имеет() на конце его, пока оно является конечным свойством. Он заявил, что вещь. Что бы то ни было, как вещь. Что бы то ни было(), но что-то вроде вещи. Другое, что бы это ни было, но вещь. Все еще(). Если это имеет смысл. Таким образом, либо нокаут более ограничительный, чем когда он дал свой разговор, или что-то еще происходит здесь. –

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