我今天遇到了一个奇怪的问题。我有一个使用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,则一切正常。我想我可以尝试尝试清理数据库,并用“”清除所有字段,如果需要,可以将它们设置为null,但是如果可以避免的话,我宁愿不这样做。

最佳答案

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

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

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


  KO将在项目列表的前面加上一个显示文本的项目
  [标题文字],并且值未定义。所以,如果myChosenValue
  保留未定义的值(默认情况下,可观察的值),然后
  虚拟选项将被选择。如果optionsCaption参数为
  可观察到的,则初始项目的文本将随着
  可观察值的变化。


我想到了以下变通办法,范围从最简单到最困难,但最“合适”:


解决方法之一是在将其作为可观察数组使用之前,将一个值未定义的条目添加到选项列表(QAManagers)中。
为选项编写一个自定义绑定处理程序,该选项允许为标题项设置给定值,而不是将其设置为undefined。这应该包括复制/粘贴KnockoutJS实现的“选项”的99%,并只是更改我在选项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);
    }

09-11 15:10