1

这是我今天遇到的一个奇怪的问题。我有一个使用 Breeze 和 Knockout 的应用程序。在我的一个页面上,我允许用户编辑和保存项目数据。保存按钮仅在进行更改时启用。为了跟踪更改,我订阅了 propertyChanged 事件。这个页面有很多下拉菜单,这会导致一些问题。这是其中一个下拉菜单的示例。

<div>
    <label for="projQAManager">QA Manager</label>
    <select id="projQAManager" data-bind="options: QAManagers,
                                          optionsText: 'FullName',
                                          optionsValue: 'USERNAME',
                                          optionsCaption: 'None',
                                          value: project().QAManager"></select>
</div>

当 project().QAManager 为“”时会出现此问题。加载项目后立即触发 propertyChanged 事件,它显示 QAManager 字段从“”更改为 null。这导致实体相信它已被修改,即使没有真正改变。如果 QAManager 已经为空,则一切正常。我想我可以通过并尝试清理数据库并清除所有带有“”的字段,如果必须的话,将它们设置为 null,但如果可以避免,我宁愿不这样做。

4

1 回答 1

1

问题确实在于 KnockoutJS 将值分配给undefined列表框的标题,您将其标记为“无”。

发生的情况是,在填充列表框后,KnockoutJS 会检查您选择的值 ( project().QAManager) 是否与列表框中列出的任何选项匹配。如果不匹配,则选择带有标题的选项,并因此修改列表框的选定值,从而触发project().QAManager获取该undefined值。

options绑定处理程序文档的摘录(重点是我的):

KO 将在项目列表前面加上一个显示文本 [caption text] 且值为undefined的项目。因此,如果 myChosenValue 的值是 undefined(默认情况下 observables 会这样做),那么将选择 dummy 选项。如果 optionsCaption 参数是一个 observable,那么初始项的文本将随着 observable 的值变化而更新

我想到了以下解决方法,从最简单到最难,但最“正确”:

  1. 一种解决方法是在选项列表 ( QAManagers) 中添加一个值为 undefined 的条目,然后才能将其作为可观察数组使用。

  2. 为选项编写自定义绑定处理程序,允许将给定值设置为标题项,而不是将其设置为undefined. 这应该包括复制/粘贴 99% 的 KnockoutJS 的“选项”实现,并且只更改我在选项 3 中编写的代码。

  3. 更改 KnockoutJS 的源代码,以便考虑新的“optionsCaptionValue”绑定,如下所示(我已经修改了原始代码,就像你应该做的那样):

        if (allBindings['optionsCaption']) {
            var option = document.createElement("option");
            ko.utils.setHtml(option, allBindings['optionsCaption']);
    
            var captionsValue;
            if (allBindings['optionsCaptionValue']) {
               captionsValue = ko.utils.unwrapObservable(allBindings['optionsCaptionValue']);
            }
            ko.selectExtensions.writeValue(option, captionsValue ? captionsValue : undefined);
            element.appendChild(option);
        }
    
于 2013-05-09T15:12:19.753 回答