确保在运行过滤器之前已填充可观察阵列

时间:2018-08-14 14:33:58

标签: javascript asp.net knockout.js asp.net-web-api2 knockout-3.0

问题:执行我的用于显示Html元素的过滤器方法时,我的web-api调用尚未填充我的可观察数组,因此没有要过滤的内容。

我的解决方案: 如果我在执行过滤器方法之前发出警报,则一切似乎都可以正常工作。 我的警报呼叫之前,我的可观察数组的长度为0,而警报之后则为一个值。

问题:如何确保在不发出警报的情况下填充阵列。 在多个页面上会发生此问题,在呈现HTML之前发出警报会使一切正常。

我有一个简单的Observable Array和一个Filter方法。 我的排除代码的一部分:

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> 

2 个答案:

答案 0 :(得分:3)

您可以简单地将GetCurrentVendor设为computedObservable,以便可以根据可观察的数组长度有条件地显示一个值。由于它是经过计算的,因此它将react对数组进行更改并更新其值。

您甚至可以将其设置为pureComputed,因此只有在调用时才能激活/计算它。

例如,当数组为空时,computedObservable 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> 

答案 1 :(得分:0)

现在,您的代码被编写为使得GetCurrentVendor仅被HTML调用一次。显然,它被称为为时过早,之后不会更新。这恰好是可观察的,以便在JS值更新时更新HTML。所以试试这个:

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>