Убедитесь, что наблюдаемый массив заполнен до запуска фильтра

1

Проблема. Когда выполняется мой метод фильтрации, который используется для отображения элемента Html, мой наблюдаемый массив еще не был заполнен моим вызовом web-api, из-за чего ничего не фильтруется.

Мое решение: если я помещаю предупреждение прямо перед выполнением моего фильтра, все, кажется, работает. Длина моего наблюдаемого массива равна 0 прямо перед моим вызовом оповещения, тогда как значение имеет значение после моего предупреждения.

Вопрос. Как я могу обеспечить, чтобы мой массив заполнялся без предупреждения. Эта проблема возникает на нескольких страницах, помещая предупреждение перед тем, как мой Html будет обработан, что все работает нормально.

У меня есть простой наблюдаемый массив и метод фильтра. Часть моего кода для нокаутов:

self.currentVendorSupport = ko.observable(new VendorContact());

//Populates Observable Array - allManufactures 
self.allManufacturers = ko.observableArray([]);
 $.getJSON(serviceRoot + '/api/Manufacturer', function (data) {  
    var mappedManufacturers = $.map(data, function (item) {
        return new Manufacturer(manID = item.manID, name = item.name);
    });
    self.allManufacturers(mappedManufacturers);
});

//Filters allManufacturers 
self.GetCurrentVendor = function () {
 alert('allManufacturerLength value again:' + allManufacturerLength);
 return ko.utils.arrayFirst(self.allManufacturers(), function (item) {
     return item.manID === self.currentVendorSupport().manID();
        });
}

Кажется, это работает. Он не работает с arrayFilter, хотя это связано с различием типа возвращаемого типа между двумя, неправильным синтаксисом или чем-то еще?

self.GetCurrentManufacturer = ko.computed(function () {
if (self.allManufacturers().length > 0) 
{ 
return ko.utils.arrayFilter(self.allManufacturers(), function (item) 
    { 
    return item.manufacturerID === 
           self.currentVendorSupport().manufacturerID() }); 
    } 
else return new Manufacturer(0, '...'); 
}, self); 

Html Code: 
<label class="control-label readOnlyLabel" data-bind="text: GetCurrentVendor().name"></label> 
Теги:
asp.net-web-api2
knockout.js
knockout-3.0

2 ответа

3
Лучший ответ

Вы можете просто сделать GetCurrentVendor computedObservable вместо этого, чтобы вы могли условно показать значение на основе длины наблюдаемого массива. Поскольку он вычисляется, он будет react на изменения, внесенные в массив, и обновить его значение.

Вы даже можете сделать его pureComputed, поэтому он всегда активируется/вычисляется при вызове.

Например, currentVendor будет показывать " ... ", когда массив пуст, и отфильтрованное имя при заполнении массива.

Вычисляется:

self.currentVendor = ko.computed(function () {
    if(this.allManufacturers().length > 0) {
        return ko.utils.arrayFirst(this.allManufacturers(), function (item) {
            return item.manID === this.currentVendorSupport().manID();
        }).name;
    } else {
        return '...'
    }
}, this)

HTML:

<label class="control-label readOnlyLabel" data-bind="text: currentVendor"></label> 
  • 0
    это путь
  • 1
    Трудно признать, но теперь дважды вы пришли и написали ответ, который имел гораздо больший смысл, чем мой, что я не мог удержаться от голосования. Я - фанат!
Показать ещё 4 комментария
0

Прямо сейчас ваш код написан таким образом, что GetCurrentVendor вызывается только один раз, по HTML. И, очевидно, это называется слишком рано и после этого не обновляется. Это именно то, что наблюдается, так что HTML обновляется при обновлении значений JS. Поэтому попробуйте следующее:

JS

self.currentVendorSupport = ko.observable(new VendorContact());

//Populates Observable Array - allManufactures 
self.allManufacturers = ko.observableArray([]);

//New observable, initially empty
self.currentVendorName = ko.observable();
  $.getJSON(serviceRoot + '/api/Manufacturer', function (data) {  
  var mappedManufacturers = $.map(data, function (item) {
     return new Manufacturer(manID = item.manID, name = item.name);
  });
  self.allManufacturers(mappedManufacturers);
  //updated value after api call is complete
  self.currentVendorName(self.GetCurrentVendor().name);
});

//Filters allManufacturers 
self.GetCurrentVendor = function () {
  //alert('allManufacturerLength value again:' + allManufacturerLength);
  return ko.utils.arrayFirst(self.allManufacturers(), function (item) {
     return item.manID === self.currentVendorSupport().manID();
  });
}

HTML

//this automatically updates when a new value is available
<label class="control-label readOnlyLabel" data-bind="text: currentVendorName"></label> 

Ещё вопросы

Сообщество Overcoder
Наверх
Меню