Knockout.js 敲除-是否可以将标准选择绑定与自定义绑定相结合?

Knockout.js 敲除-是否可以将标准选择绑定与自定义绑定相结合?,knockout.js,jquery-chosen,Knockout.js,Jquery Chosen,这不起作用(调用了自定义绑定,但下拉列表为空) 更新 .选定({}) 是来自另一段Javascript(harvesthq.github.io/selected)的方法 我意识到,当它被注释掉时,剩下的装订工作就完成了。 我真正需要的是在所有其他绑定完成后运行“$(element).selected({});” 更新2 当我在应用了所有绑定之后手动应用“selected”时,它工作得很好。我可以使用一个按钮来运行这个JS 我只需要在所有绑定完成后自动执行(回调函数?)。 我不知道怎么做 更新3

这不起作用(调用了自定义绑定,但下拉列表为空)

更新

.选定({})

是来自另一段Javascript(harvesthq.github.io/selected)的方法

我意识到,当它被注释掉时,剩下的装订工作就完成了。 我真正需要的是在所有其他绑定完成后运行“$(element).selected({});”

更新2

当我在应用了所有绑定之后手动应用“selected”时,它工作得很好。我可以使用一个按钮来运行这个JS

我只需要在所有绑定完成后自动执行(回调函数?)。 我不知道怎么做

更新3

“parentAreas”不是静态数组。它是从web服务加载的:

function ViewModel() {

    var self = this;

   self.init = function () {

        //load parent areas from web service
    };

    self.init(); //Running the init code
}

ko.applyBindings( new ViewModel());
我想初始化“选定”框自定义绑定时,父区准备就绪

更新4

新版本(工作正常,但不可重用,因为它具有硬编码绑定)

ko.bindingHandlers.selected={ init:function(元素、valueAccessor、allBindingsAccessor、viewModel、上下文){

//而绑定只是数据绑定=“selected:{}

更新5 避免多次初始化(黑客方式)

更新6


我已经编写了通用解决方案(见下面的答案)

是的,只需重新排序绑定(fiddle:):



我认为您的问题在于
选择的
插件本身。当您在
选择的
标签上应用
选择的
时,它会更改其标记(它不再是普通的html
选择的

因此,在绑定过程中,首先应用
所选的
自定义绑定,然后更改html标记,因此绑定无法正常工作

要解决此问题,您需要在最后一次应用自定义绑定,而不是在第一次应用。这样,ko绑定将正常应用,然后应用自定义绑定并更改select(但现在您已正确构建select)

更新

要在生成
选项
元素后运行函数,可以使用
选项AfterRender
回调..查看文档


另一个肮脏的解决方案是使用
settimeout

这是一种反模式,取决于绑定的顺序

如果自定义绑定需要先运行其他绑定,则应该从自定义绑定调用这些绑定,如

ko.applyBindingsToNode(element, { options: arr, value: val });
然后做
$(元素)。选择

通用解决方案

HTML

javascript是

   ko.bindingHandlers.comboBox = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
        var bindings = valueAccessor();
        var optionsObservableArray = bindings.options;
        optionsObservableArray.subscribe(function (newObservableArray) {

            if (newObservableArray && newObservableArray.length > 0) {

                if (element.comboBoxInitialised) {
                    return;
                }

                ko.applyBindingsToNode(element, {
                    options: bindings.options,
                    optionsCaption: bindings.optionsCaption,
                    optionsText: bindings.optionsText,
                    value: bindings.value
                });
                $(element).chosen({});
                element.comboBoxInitialised = true;
            }
        });
    }
};

什么是$(element).selected({});好问题。“.selected({});”是另一段Javascript()中的一个方法。我意识到当它被注释掉时,剩下的绑定工作就完成了。我需要的是运行“$(element).selected({});“在所有其他绑定完成后。必须有可能使此通用思想不应应用多次,这种方法不受支持,如果它起作用,那就走运了。在2.3版本中,它实际上会抛出一个错误,表示不能再应用绑定。”once@Anders-非常感谢,威尔。谢谢!这是我在“更新”部分写的:我真正需要的是在所有其他绑定完成后运行“$(element).selected({});”。“但是我不知道怎么做。@MaximEliseev请检查这里的文档::注意optionsAfterRender对选择列表中的每个项目都运行。我可以对它进行编程,使它只对第一个项目运行。我会是一个有点粗糙的解决方案。我可以试试。它没有样式(没有加载所选的css),但它应该可以工作。如果单击第一个文本框并单击一个选项,它将被选中。更新的fiddle:,检查ConsoleEyes,版本5(jsfiddle.net/gBhbx/5)在jsfiddle中工作。我已删除(非常混乱)“chosenSimple”选择和示例仍然有效不要这样做,它不是实心的,会断裂easily@pax162-在JSFIDLE中工作,但在我的解决方案中不起作用。我将研究一下JSFIDETHAKS!如果“arr”是一个静态数组,它就可以工作。但是它是从web服务加载的(请参阅更新3)。因此,当初始化“所选”自定义绑定时,它是空的。您需要使用observableArray,然后parentAreas是observableArray;self.parentAreas=ko.observableArray([]);
 function run() {
    $('.chosen-select').chosen({});
};    
function ViewModel() {

    var self = this;

   self.init = function () {

        //load parent areas from web service
    };

    self.init(); //Running the init code
}

ko.applyBindings( new ViewModel());
        viewModel.parentAreas.subscribe(function(newParentAreas) {
            if (newParentAreas && newParentAreas.length > 0) {

                ko.applyBindingsToNode(element, {
                    options: viewModel.parentAreas,
                    optionsCaption: 'Choose...',
                    optionsText: 'Label',
                    value: viewModel.selectedParentArea
                });
                $(element).chosen({});
            }
        });
    }
};
ko.bindingHandlers.parentAreaComboBox = {

    initialised: false,
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {

        viewModel.parentAreas.subscribe(function (newParentAreas) {

            if (newParentAreas && newParentAreas.length > 0) {

                if (ko.bindingHandlers.parentAreaComboBox.initialised) {
                    return;
                }
                ko.applyBindingsToNode(element, {
                    options: viewModel.parentAreas,
                    optionsCaption: 'Choose...',
                    optionsText: 'Label',
                    value: viewModel.selectedParentArea
                });
                $(element).chosen({});
                ko.bindingHandlers.parentAreaComboBox.initialised = true;
            }
        });
    }
};
<select id="parentArea" class="chosen-select" data-bind="   
   options: parentAreas,
   optionsCaption: 'Choose...',
   optionsText: 'Label',
   chosen:{},
   value: selectedParentArea">
</select>
ko.applyBindingsToNode(element, { options: arr, value: val });
   ko.bindingHandlers.comboBox = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
        var bindings = valueAccessor();
        var optionsObservableArray = bindings.options;
        optionsObservableArray.subscribe(function (newObservableArray) {

            if (newObservableArray && newObservableArray.length > 0) {

                if (element.comboBoxInitialised) {
                    return;
                }

                ko.applyBindingsToNode(element, {
                    options: bindings.options,
                    optionsCaption: bindings.optionsCaption,
                    optionsText: bindings.optionsText,
                    value: bindings.value
                });
                $(element).chosen({});
                element.comboBoxInitialised = true;
            }
        });
    }
};