Knockout绑定选择动态可观察数组

时间:2014-07-02 08:54:08

标签: javascript knockout.js ko.observablearray

我遇到了使用knockout选择控件的动态绑定问题。我想要实现的是一段代码,它将observableArray的可观察对象绑定到select选项。 observableArray中的'objects'不断变化。

存储在observableArray中的对象,我们称之为sampleObj,有一些属性(ko.observables),如name,lastName和phoneNumber。我想显示observableArray中存储的所有对象的选项选项lastNames。

我对cshtml中observable的绑定如下:

<select data-bind="options: sampleObservableArray, optionsText: lastName, optionsCaption: 'choose...'"></select>

并且除了'choose ...'文本之外它不会显示任何内容。 sampleObservableArray的内容在js中更新,我可以随时使用console.log它。我绑定值的方式有什么不对,或者我应该以某种方式强制刷新select控件? 当然作为一个完整的业余爱好者,我已经尝试了所有可能的使用和不使用parethnesis的组合:)但仍然没有效果。

sampleObservableArray - 包含sampleObj的ko.observableArray

sampleObj - ko.observable,带有一些属性,如name,lastName和phoneNumber,其中所有属性都是ko.observables。

修改 回答@ Tomalak的问题,有一个代码可以更清晰。首先,sampleObj模型:

define('sampleObj',
['ko'],
function (ko) {
    var
        SampleObj = function () {
            var self = this;
            self.name = ko.observable();
            self.lastName = ko.observable();
            self.phoneNumber = ko.observable();
            return self;
        };

    return SampleObj;
});

然后将sampleObj对象添加到observableArray:

// newData is an argument of a function triggered by signalR action, and returns strings as its properties
var sampleObj = ko.observable(new SampleObj()
    .name(newData.name)
    .lastName(newData.lastName)
    .phoneNumber(newData.phoneNumber);

var sampleObjEntry = ko.utils.arrayFirst(sampleObservableArray(), function (item) {
    return item().phoneNumber() === newData.phoneNumber;
});
// if object with the phoneNumber already exits replace it, if not - add
if (!sampleObjEntry) {
    sampleObservableArray.push(sampleObj);
} else {
    sampleObservableArray()[sampleObservableArray().indexOf(sampleObjEntry)] = sampleObj;
    sampleObservableArray.valueHasMutated();
}

不知道是否有帮助。

1 个答案:

答案 0 :(得分:0)

我创建了简单的JSFiddle Demo *,它按预期工作 我认为您的代码中的问题符合

sampleObservableArray()[sampleObservableArray().indexOf(sampleObjEntry)] = sampleObj;

您应该从数组中删除sampleObjEntry,然后推送sampleObj或更新已存在的sampleObjEntry

例如:

...
else {
    sampleObjEntry.name(newData.name);
    sampleObjEntry.lastName(newData.lastName);
    sampleObjEntry.phoneNumber(newData.phoneNumber);
}  

....
else {
    sampleObservableArray.remove(sampleObjEntry);
    sampleObservableArray.push(sampleObj);
}    

* JSFiddle演示源

<强>的Javascript

function Person(name, lastName, phone)
{
    return {
        name : ko.observable(name),
        lastName : ko.observable(lastName),
        phoneNumber : ko.observable(phone)
    }
}

var vm = {
    sampleObservableArray : ko.observableArray(),
    addPerson : function()
    {
       var newPhone = document.getElementById("_phone").value,
           newName = document.getElementById("_name").value,
           newLastName = document.getElementById("_lastName").value;
       var existentPerson = ko.utils.arrayFirst(vm.sampleObservableArray(), function(item)
                                                {
                                                    return item.phoneNumber() == newPhone;
                                                })
       if (existentPerson)
       {
           existentPerson.name(newName);
           existentPerson.lastName(newLastName);
           existentPerson.phoneNumber(newPhone);
       }
       else
       {
           vm.sampleObservableArray.push(new Person(newName, newLastName, newPhone))
       }


    }
}

vm.sampleObservableArray.push(new Person("Ronald", "McDonald", "1"))
vm.sampleObservableArray.push(new Person("Michael", "McConnel", "2"))

ko.applyBindings(vm)    

Html

<select data-bind="options: sampleObservableArray, optionsText: 'lastName', optionsCaption: 'choose...'"></select>  
<br/>
<label for="_name">Name:</label><input id="_name"/><br/>
<label for="_lastName">Last Name:</label><input id="_lastName"/><br/>
<label for="_phone">Phone:</label><input id="_phone"/><br/>
<button data-bind="click: addPerson">Add person</button>