无法绑定到异步加载的数组 - Knockout

时间:2014-08-25 17:03:24

标签: ajax asynchronous knockout.js binding

我有一个模型,我正在尝试加载observableArray,但由于某种原因绑定不起作用。如果我将项目放入定义模型的数组中,它将绑定,但如果我执行ajax调用来加载项目,则不会绑定它们。异步加载项目的最佳方法是什么?这是模型:

 function Clinic() {

var self = this;

self.searchType = ko.observable();
self.clinicName = ko.observable();
self.providerSpecialty = ko.observable();
self.address = ko.observable();
self.city = ko.observable();
self.county = ko.observable();
self.state = ko.observable();
self.network = ko.observable();
self.zip = ko.observable();
self.searchDistance = ko.observable("10");
self.nameSearchType = ko.observable();

self.cityOptions = ko.observableArray(['City a', 'city b', 'city c']);
self.countyOptions = ko.observableArray(['Ada, ID', 'Adair, IA', 'Adams, ND']);
self.stateOptions = ko.observableArray(['AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MI', 'MN', 'MO', 'MS', 'MT', 'NE', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'NV', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VT', 'WA', 'WI', 'WV']);
self.nameSearchTypeOptions = ko.observableArray(['Starts With', 'Contains']);

self.specialties = ko.observableArray();

self.nextButtonEnable = ko.computed(function () {

    return typeof this.searchType() === "undefined" ? false : true;

}, self);

}

我正试图加载self.specialties而没有任何运气。这是我正在使用的代码:

 loadSpecialties: function () {



                $.ajax({
                    type: "POST",
                    url: "clinic-search.aspx/GetAllSpecialties",
                    data: "{}",
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    async: false,
                }).done(function (data) {
                    $(data.d).each(function (i, e) {
                        vm.clinic().specialties().push(e.Description);
                    });
                });

            },

在执行vm.loadSpecialties()之前我正在调用ko.appliBindings(vm),但这些项目没有受到约束。我甚至写了一个函数来检查数组中是否有东西,它告诉我有140个项目。

 checkSpecialties: function () {
                alert("length: " + vm.clinic().specialties().length);
                alert("first: " + vm.clinic().specialties()[0]);
            },

这是我想要绑定的HTML。就像我之前所说的那样,如果我将项目硬编码到专业数组中,它将起作用,但它不适用于ajax调用。有任何想法吗?

 <div id="Name" data-bind="with: clinic, visible: showName">
            <div>
                <p>Name options...</p>
                <div>
                    <p class="bold">Enter all or part of the clinic name.</p>
                    <div>
                        <input type="text" data-bind="value: clinicName" />
                        <select data-bind="options: nameSearchTypeOptions, value: nameSearchType"></select>
                    </div>
                    <hr />
                    <p class="bold">Select a provider specialty, if one is preferred.</p>
                    <select data-bind="options: specialties, value: providerSpecialty"></select>
                </div>
                <input type="button" value="Start Over" class="btn btn-primary btn-sm" data-bind="click: $parent.startOver" />
                <input type="button" value="check specialties" class="btn btn-primary btn-sm" data-bind="click: $parent.checkSpecialties" />
            </div>
        </div>

1 个答案:

答案 0 :(得分:0)

您正在更新观察到的基础数组,但您没有通知任何订阅者。

你可以做的最简单的事情是推入可观察数组,而不是底层数组。或者,如果您想最小化通知,请插入基础数组(如您所示),但最后通过调用valueHasMutated()手动通知订阅者。

$(data.d).each(function (i, e) {
    // note: not invoking specialties
    vm.clinic().specialties.push(e.Description);
});

// or
$(data.d).each(function (i, e) {
    vm.clinic().specialties().push(e.Description);
});
vm.clinic().specialties.valueHasMutated();

然而,一般来说,在将值加载到可观察数组中时,我认为最好将值加载到新数组中,然后将数组设置为observable。

vm.clinic().specialties(
    ko.utils.arrayMap(data.d, function (e) {
        return e.Description;
    })
);