Javascript 选择带2个optgroups带敲除的生成将值重置为空

Javascript 选择带2个optgroups带敲除的生成将值重置为空,javascript,dom,knockout.js,Javascript,Dom,Knockout.js,我有这个HTML <select data-bind="value: $data.id"> <optgroup label="Regions" data-bind="foreach: countries.regions.names"> <option data-bind="html: $data.name, value: $data.value"></option> </optgroup> &l

我有这个HTML

<select data-bind="value: $data.id">
    <optgroup label="Regions" data-bind="foreach: countries.regions.names">
        <option data-bind="html: $data.name, value: $data.value"></option>
    </optgroup>

    <optgroup label="Countries" data-bind="foreach: shipping.allCountries">
        <option data-bind="html: $data.name, value: $data.code"></option>
    </optgroup>

</select>
但是在通过敲除构建
select
之后,
this.id()
的值为空,并将返回
undefined
。当我订阅该字段时,它会通知我该字段正在更新,但没有任何内容

我的当前(脏)修复:

这是可行的,但当然不推荐这样做

另外,在
选择中选择另一个元素并返回原始值后,也可以

如何解决此问题


注意:已选择正确的元素

请确保您的国家/地区名称实际指向正确的位置。如果这些选项不存在,那么这些值就不存在

失败的原因是
元素的
值是在使用
foreach
绑定其内容之前绑定的,如果无法选择模型值,则
绑定会将模型值重置为元素中当前选择的值

问题示例:

有两种解决方案

1.防止重置模型值 一种解决方案是使用Knockout 3.1(目前为Beta版)
valueAllowUnset
中提供的新绑定选项,防止
绑定重置模型值

<select data-bind="value: $data.id, valueAllowUnset: true">
绑定:

ko.bindingHandlers.bindInner = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        ko.applyBindingsToDescendants(bindingContext, element);
        return { controlsDescendantBindings: true };
    }
};
例如:

推荐
第一个选项使用内置解决方案,但有一个缺点,即用户界面选择使用
setTimeout
(在
绑定中)进行。因此,在初始化视图时,可以在选择中看到可见的更改。我认为,第二种选择是更好的,当然,您可以同时使用这两种方法来双重解决问题。

$data
是隐式的,您不必使用它(即
等也可以)。当然,除非有同名的全局变量。我喜欢保持它的整洁,防止全局变量出现任何问题。这是一个很大的应用程序。如果你想保持它的整洁,你应该避免使用全局应用程序而且,这不是一个问题。局部变量会影响全局变量,在这里,范围界定问题不可能影响你。请参阅(除此之外,如果您绑定的对象不是
$data
的属性,它甚至会失败并出现错误。Knockout不会自动使用
$data
以外的任何内容)谢谢,但这很好。一切正常,所有数据都填写正确。第三种解决方案是防止黑客完全绕过这个问题:使用一个自动完成库和一个普通的旧文本字段,而不是预先填充的
。或者,select上的
optgroups
自定义绑定也可以实现这一点。
<select data-bind="value: $data.id, valueAllowUnset: true">
<select data-bind="bindInner, value: $data.id">
ko.bindingHandlers.bindInner = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        ko.applyBindingsToDescendants(bindingContext, element);
        return { controlsDescendantBindings: true };
    }
};