我今天遇到了一个奇怪的问题。我有一个使用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);
}