简体   繁体   English

淘汰赛剑道通过可计算的可观察性绑定

[英]knockout-kendo issues binding through computed observable

I am attempting to use knockout-kendo.js to declare a kendo dropdownlist control in a knockout forEach template, so that as new items are added to the knockout observable array, new kendo dropdownlists are rendered in the UI. 我试图使用敲除-kendo.js在敲除forEach模板中声明kendo dropdownlist控件,以便在将新项目添加到敲除可观察数组中时,新的kendo dropdownlists呈现在UI中。

Initially, I come to realize that I can no longer bind the dropdownlist's selected value to an entire entry object in my dropdownlist's specified 'data' array. 最初,我意识到我无法再将下拉列表的选定值绑定到下拉列表的指定“数据”数组中的整个条目对象。

To overcome this issue, I followed the RP Niemeyer's suggestion in the following thread: Set the binding of a dropdown in knockout to an object 为了克服此问题,我在以下线程中遵循了RP Niemeyer的建议: 设置击倒中的下拉列表与对象的绑定

Now, this all works. 现在,这一切正常。 Great. 大。

My issue is when attempting to add second drop down list to the template, who's data is bound to an array property on the object being returned from the computed observable... (I need to chain the drop down lists so that the first displays all Students, second displays all classes for the student that is currently selected in the first drop down list, third displays all test grades for the class that is currently selected in the second drop down list, etc....) 我的问题是,当尝试向模板添加第二个下拉列表时,谁的数据绑定到从可计算的observable返回的对象的数组属性上……(我需要链接下拉列表,以便第一个显示所有学生,第二个显示第一个下拉列表中当前选择的学生的所有课程,第三个显示第二个下拉列表中当前选择的学生的所有考试成绩,等等。)

I created a fiddle based on RP Niemeyer's original fiddle to demonstrate my issue: 我根据RP Niemeyer的原始小提琴创建了一个小提琴,以演示我的问题:

Original Fiddle (RP Niemeyer's) 原始小提琴(RP尼迈耶的)

My Fiddle With Issues 我的小提琴与问题

I added the below lines to the fiddle: 我在小提琴中添加了以下几行:

HTML: HTML:

<input data-bind="kendoDropDownList: { dataTextField: 'caption', dataValueField: 'id', data: selectedChoice().shapes, value: selectedShapeId }" />

JS: JS:

this.choices = ko.observableArray([
        { id: "1", name: "apple", shapes: ko.observableArray([ { id: "5", caption: "circle" }, { id: "6", caption: "square" }]) },
        { id: "2", name: "orange", shapes: ko.observableArray([ { id: "5", caption: "circle" }]) },
        { id: "3", name: "banana", shapes: ko.observableArray([ { id: "5", caption: "circle" }, { id: "6", caption: "square" }, { id: "7", caption: "triangle" }]) }
    ]);

Again, I was expecting that upon the selection changing in the first drop down list (causing selectedId to change, causing selectedChoice to change) would also cause any UI elements bound to 'selectedChoice' or any of selectedChoices' properties, to have their bindings re-evaluated and UI respectively updated. 再次,我期望在第一个下拉列表中更改选择(导致selectedId发生更改,导致selectedChoice发生更改)时,也会导致绑定到“ selectedChoice”的任何UI元素或任何selectedChoices的属性重新绑定-评估和用户界面分别更新。

Am I missing something? 我想念什么吗? Or is there a better way to achieve this 'chaining of drop down list' behavior (while still utilizing a knockout template and kendo drop down list control)? 还是有一种更好的方法来实现这种“链接下拉列表”行为(同时仍使用敲除模板和kendo下拉列表控件)?

Let me offer you some advice. 让我为您提供一些建议。 Try to avoid accessing properties of an observable's value, as you can see, the dependency detection will not always be able to detect the dependency. 如您所见,请尝试避免访问可观察值的属性,依赖关系检测将无法始终能够检测到依赖关系。 You should create a computed observable which does the accessing for you. 您应该创建一个计算的observable来为您完成访问。

var ViewModel = function () {
    // ...

    this.selectedChoice = ko.computed(function () {
        var id = this.selectedId();
        return ko.utils.arrayFirst(this.choices(), function(choice) {
           return choice.id ===  id;
        });
    }, this);
    this.selectedChoiceShapes = ko.computed(function () {
        var selectedChoice = this.selectedChoice();
        return selectedChoice && selectedChoice.shapes;
    }, this);
}

Then your bindings becomes: 然后您的绑定变为:

<input data-bind="kendoDropDownList: {
                      dataTextField: 'name',
                      dataValueField: 'id',
                      data: choices,
                      value: selectedId }" />
<input data-bind="kendoDropDownList: {
                      dataTextField: 'caption',
                      dataValueField: 'id',
                      data: selectedChoiceShapes,
                      value: selectedShapeId }" />

updated fiddle 更新的小提琴

This appears to be a shortcoming of Kendo using Knockout. 这似乎是Kendo使用Knockout的缺点。 When Kendo evaluates selectedChoice().shapes it holds onto the array it finds, instead of keeping the entire expression. 当Kendo评估selectedChoice().shapes它将保留在找到的数组上,而不是保留整个表达式。 If you update that specific array with options, you can see them in the second dropdown. 如果使用选项更新该特定阵列,则可以在第二个下拉列表中看到它们。 The problem is that when you update selectedChoice Kendo does not reevaluate the data to the new shapes array. 问题是,当您更新selectedChoice Kendo时,它不会将数据重新评估到新的shapes数组。 You can see this behavior in this fiddle . 您可以在这个小提琴中看到这种行为。

Open the JS console, set the context to the fiddle (it defaults to the top frame in Chrome`, and run this: 打开JS控制台,将上下文设置为小提琴(默认为Chrome`的top frame ,然后运行以下命令:

window.vm.choices()[1].shapes.push({"id": "6", "caption" : "Thing"})

And you will see the second dropdown update. 然后您将看到第二个下拉更新。 Changing the first dropdown doesn't have an effect. 更改第一个下拉菜单无效。 You can see that in this fiddle Knockout without kendo reevaluates the entire expression, properly updating the second select options. 您可以看到,在没有kendo的情况下, Knockout会重新评估整个表达式,并正确更新了第二个select选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM