从远程源分配knockout可观察值

时间:2012-08-22 12:03:41

标签: knockout.js

我有以下的淘汰视图模型:

function DepartmentsViewModel() {
    var self = this;

    self.currentComplaint = ko.observable('');
    self.departments = ko.observableArray([]);
    self.selectedDepartment = ko.observable('').extend({
        required: true
    });

}

然后我填充我的部门并为selectedDepartment值分配一系列远程调用到我的控制器(id只是我根据用户当前页面分配给变量的数字):

$(function() {
    var self = new DepartmentsViewModel();

    self.currentComplaint(id);

    $.ajax({
        url: '@Url.Action("GetDepartments")',
        success: function (data) {
            self.departments(data);
        }
    });

    $.ajax({
        url: '@Url.Action("GetDetails")',
        data: { id: id },
        success: function (data) {
            self.selectedDepartment(data.DepartmentId);
        }
    });

    ko.applyBindings(self);

});

然后在我的HTML中填充,如下所示:

<select class="complaint-select" 
        data-bind="options: departments, 
                   optionsText: function(item) { 
                       return item.DepartmentCode + ' - ' + item.DepartmentName 
                   }, 
                   optionsValue: 'DepartmentId',
                   value: selectedDepartment, 
                   optionsCaption: 'Choose..'">
</select>

我注意到,当我刷新页面时,有时我的selectedDepartment没有设置,因此,我的下拉列表没有设置任何值,并告诉我从下拉列表中选择一个选项?知道为什么?我已经在我的AJAX请求的console.log(self.selectedDepartment());操作上完成了complete,有时它已经设置好了,但其他一些是未定义的。

2 个答案:

答案 0 :(得分:2)

您不必进行separete ajax调用,而是必须链接这些ajax调用,以确保对于任何给定的id,您的departmantArray中始终存在有效的deparmantList。因为ajax调用的结果是随机的,你无法确定哪一个是第一个。

var departmantLoadProcess =  $.ajax({
        url: '@Url.Action("GetDepartments")'      
});

departmantLoadProcess.done(function(data){

    self.departments(data);

    var detailLoadProcess = $.ajax({
        url: '@Url.Action("GetDetails")',
        data: { id: id },
        success: function (data) {         
        }
    });

    detailLoadProcess.done(function(data){
       self.selectedDepartment(data.DepartmentId);
    });

});

有关更多信息,请检查Jquery deferred object

修改

就像Ryan提到的那样,如果我们获得数百万的命中率,那么ajax请求会导致一些超载:)如果他们的结果不依赖于彼此,我们就不需要等待它们。我们可以进一步优化它。

// If both ajax request success

$.when( $.ajax({url: '@Url.Action("GetDepartments")'}),
        $.ajax({url: '@Url.Action("GetDetails")' , data : {id:id}}) ).done(function(deparmantsData,detailsData) {

   self.departments(deparmantsData);
   self.selectedDepartment(detailsData.DepartmentId);

});

答案 1 :(得分:0)

Knockout尝试强制您根据当前选项进行了有效选择。听起来有时候您所选部门的AJAX请求会在部门列表之前返回。在这种情况下,所选部门实际上并不在部门列表中。

一些选项:

  • 找到一种方法来生成一个返回所需数据的单个请求
  • 如果尚未填充部门,请在选项中添加虚拟条目。类似的东西:

    success: function (data) {
        if (!self.departments().length) {
            self.departments.push(data);
        }
        self.selectedDepartment(data.DepartmentId);
    }
    

然后当部门进来时,他们可以覆盖这个虚拟条目。