考虑select
元素上的以下ko绑定:
<select data-bind="value: valueObservable, options: optionsObservableArray,
optionsCaption: '[None] - this is an optional field'">
...给出如下的viewmodel:
function MyViewModel()
{
var self = this;
self.valueObservable = ko.observable();
self.optionsObservableArray = ko.observableArray();
// ajax call to load options
ko.computed(function() {
$.ajax(...)
.success(function(optionsResponse) {
self.optionsObservableArray(optionsResponse)
});
});
// ajax call to load data value
ko.computed(function() {
$.ajax(...)
.success(function(valueResponse) {
self.valueObservable(valueResponse)
});
});
}
这有什么奇怪的,当第二个(数据)ajax调用在第一个(选项)ajax调用之前返回时。由于select
元素具有optionsCaption
绑定,因此我认为这是正在发生的事情:
valueObservable
设置为某个值(如6,abc或其他一些非虚假值)。 option
元素中只有select
(由于optionsCaption
),并且因为valueObservable
绑定了它(通过{{1 }}绑定),这会导致value
更改为valueObservable
。undefined
完成并向optionsObservableArray
添加新的option
元素,但此时为时已晚:select
现在正在包裹valueObservable
1}}值而不是第一个ajax调用返回的实际数据值。问题:解决此问题的最佳方法是什么?这是我能想到的:
undefined
进行第一次ajax调用。这可能会降低页面渲染速度。async: false
)。然后订阅value: selectedValueObservable
并使用订阅执行optionsObservableArray
之类的操作。这似乎是一个绑带修复。self.selectedValueObservable(self.valueObservable())
。更新
为了简化示例代码,我在此问题中省略了另一个问题。实际上,此视图模型用于创建可编辑的数据项列表。因此实际上有超过1个下拉列表被呈现到页面。数据ajax调用确实返回一个数组,其成功函数实际上设置了observableArray
个复杂项。由于下拉列表选项在每个内联表单中都被重用,因此它被放置在observableArray
视图模型上,并且只加载一次。在单个ajax调用中传递选项也很困难,因为数据项是通过WebAPI检索的(返回$parent
,没有空间发送额外的下拉选项)。
答案 0 :(得分:1)
如果有可能的话,我建议你进行一次ajax调用。使控制器返回包含对象数组和选定值的复杂对象:
// ajax call to load options and data value
ko.computed(function() {
$.ajax(...)
.success(function(response) {
self.optionsObservableArray(response.options);
self.valueObservable(response.value);
});
});
如果无法合并两个ajax调用,你可以调用第二个ajax来成功回调第一个ajax:
// ajax call to load options
ko.computed(function() {
$.ajax(...)
.success(function(optionsResponse) {
self.optionsObservableArray(optionsResponse)
// ajax call to load data value
$.ajax(...)
.success(function(valueResponse) {
self.valueObservable(valueResponse)
});
});
});
答案 1 :(得分:1)
有没有理由不首先进行ajax调用,并且在完成后使用applyBinding?
$.when(getOptions(), getData()).done(bind)
function getOptions() {
return $.ajax(...).success(vm.optionsObservableArray)
}
function getData() {
return $.ajax(...).success(vm.valueObservable)
}
function bind() {
ko.applyBindings(vm, document.getElementById('elem'))
}