Проблема. Когда выполняется мой метод фильтрации, который используется для отображения элемента 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>
Вы можете просто сделать 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>
Прямо сейчас ваш код написан таким образом, что 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>