淘汰赛将选择绑定到动态可观察数组

Posted

技术标签:

【中文标题】淘汰赛将选择绑定到动态可观察数组【英文标题】:Knockout bind select to dynamic observable array 【发布时间】:2014-08-22 23:47:26 【问题描述】:

我在使用淘汰赛选择控件的动态绑定方面遇到问题。我想要实现的是一段代码,它将可观察对象的 observableArray 绑定到选择选项。 observableArray 中的“对象”不断变化。

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

我对 cshtml 中的 observable 的绑定如下所示:

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

除了“选择...”文本之外,它不显示任何内容。 sampleObservableArray 的内容在 js 中更新,我可以随时 console.log 它。我绑定值的方式有什么问题,或者我应该以某种方式强制刷新选择控件吗? 当然,作为一个完全的业余爱好者,我已经尝试过所有可能的使用和不使用 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();

不知道有没有用。

【问题讨论】:

与其冗长地描述您的数据模型的结构,不如简单地展示一个示例?这将使每个人的事情变得更容易。甚至可能设置一个 jsFiddle。 (此外,optionsText: 绑定应该是一个字符串) @Tomalak optionsText 绑定也适用于with a function @GôTô 是的,我知道。然而,根据 OP 的描述,我希望在那里看到'lastName',而不是lastName()。在这种情况下,使用 函数结果,它可以是任何东西,但不一定引用 sampleObservableArray 中任何对象的属性。所以我倾向于说这是一个错误。 @Tomalak 确实!尽管我们拥有的代码很少,但很难说 就像我怀疑的那样。使用optionsText: 'lastName'。 (提示:您是在告诉剔除它应该使用的属性的 name。)另外 - 为什么要将 SampleObj 包装在另一个 observable 中?那应该是不必要的。 【参考方案1】:

我创建了简单的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>

【讨论】:

感谢您的回答!我已经用你的代码替换了我的代码,但仍然没有成功。即使没有这些改进,我相信在我的代码中首先应该添加新值并显示在下拉列表中,但事实并非如此。更重要的是,谢谢你的小提琴。我对其进行了一些更改,以便该按钮将向 observableArray 添加一个新条目,但它不起作用!也许我在那里犯了一些错误?你能看看吗? jsfiddle.net/qyQ36/1 嗯,谢谢,那太傻了,我希望我在那里找到了我的问题。

以上是关于淘汰赛将选择绑定到动态可观察数组的主要内容,如果未能解决你的问题,请参考以下文章

选择可观察的值和文本

Knockout.js Select2 绑定。将 Select2 升级到 v4 后损坏

在knockoutjs上绑定按键事件,未填充可观察到

Knockoutjs 选项与 JSON 数据绑定?

淘汰赛可观察数组

淘汰赛可观察格式