Knockout.Js没有检测到以编程方式更改的复选框状态

时间:2013-01-03 16:51:33

标签: jquery knockout.js

我有一个简单的复选框,其价值由我在localStorage中写入持久状态的一些基础设施调整。我知道这通常是通过设置viewModel来完成的,但 基础结构不知道任何敲除绑定并且无法访问它们。

我不认为这会是一个问题,因为我认为淘汰赛已经在'变更'事件中运行,但是$checkbox.prop('checked', true).trigger('checked')无法触发我的观察。即使直接使用点击事件也不能满足我的需要。

击球线会发生什么事?如何让它读取控件的状态?

jsbin showing this weird behavior here。尝试直接选中复选框,然后单击按钮。

7 个答案:

答案 0 :(得分:2)

我找到了一种更好的方法。只需将此代码放在您的domready事件中:

    $("input:checkbox").bind('change', function () {
        $(this).triggerHandler('click');
    });

答案 1 :(得分:1)

Knockout绑定并不像你想的那样真正起作用。

退房:http://knockoutjs.com/documentation/custom-bindings.html

这是一个你可以使用的解决方案,没有jQuery,没有自定义绑定。

你的HTML会保持不变。

var m = {
  isChecked: ko.observable(false),
  infrastructureUpdatesCheckbox: function() {
    this.isChecked( this.isChecked() === true ? false : true);
  }
};

ko.applyBindings(m);

答案 2 :(得分:1)

你应该更改复选框'通过您的视图模型检查状态:

 var m = {
   isChecked: ko.observable(false)
  //,infrastructureUpdatesCheckbox: function() {
    //$chk = $(':checkbox');
    //$chk
    //  .prop('checked', !$chk.prop('checked'))
    //  .trigger('change');
    //this.isChecked(!this.isChecked());  // this - is your view model
 }
};

这里是更新版本:

function InfrastructureUpdatesCheckbox(){

  var $cb = $(':checkbox');
  var cb = $cb[0];
  cb.checked = !cb.checked;  // manually change checked status
  $cb.triggerHandler('click');  // run all event handlers bound to 'click' event
}

我猜这个问题只与复选框(单选按钮)有关。当您手动触发事件时,其他控件应该正确运行。

答案 3 :(得分:1)

您可能已经找到了问题的解决方案,但这可能有助于其他人。

我遇到了完全相同的问题。我所做的是使用pub-sub模式并让我的组件触发自己的更改事件。您可以做的是让需要更新模型的基础架构组件实例订阅该事件,然后更新您的模型。更好的是,您的模型可以订阅事件,这样您的模型就可以了解基础架构组件而不是相反的方式

通过这种方式,您的基础架构组件无需了解ko,您可以在其他任何地方重复使用它。我相信如果您计划重新使用该组件,那么在找到其他用途之前,这只是一个时间问题。

希望这会有所帮助(抱歉没有代码,因为我无法在SO上发布客户代码,但如果有人想要一个例子就这么说,我会做一个jsfiddle来说明。

答案 4 :(得分:1)

在我的情况下,这被证明与jquery bug有关。我带着github淘汰赛问题跟踪器来跟踪这个问题; see here

最终我最终在我的组件中执行此操作:

var isjQueryOld = /^(0|1)\.[0-8]\./.test($.fn.jquery); // <=1.8.*
var toggleCheckbox = isjQueryOld ? jQueryOldToggleCheckbox : function($el) { $el.trigger('click') } //https://github.com/knockout/knockout/issues/987


function jQueryOldToggleCheckbox($el) {
    //This should be simple right? See http://stackoverflow.com/a/8595601/5056
    //and "simulating events to adjust knockout models" jasmine spec
    //all this is nessessary to get everything working with knockout
    var changeTo = !$el.prop('checked');
    if(changeTo)
        $el.attr('checked', true);
    else
        $el.removeAttr('checked');
    $el.trigger('click');
    $el.prop('checked', changeTo);
}

并在我的代码中

        toggleCheckbox($el);

答案 5 :(得分:0)

我不知道敲门的内容是什么,你可能会涉及到源本身并弄明白,但一种解决方案是使用custom binding。在自定义绑定的init中,您可以为要捕获的任何事件(例如changed)设置所需的处理程序,并使用它来强制绑定以运行update。< / p>

答案 6 :(得分:0)

我今天已经花费了数小时来使用点击和点击的方法进入点击循环,尝试使用ko.observable,pureComputed编写甚至是InfrastructureUpdatesCheckbox都没有太长时间,无法向任何为我的工作付费的人解释为什么我不能检查该死的淘汰赛中的单选按钮。不幸的是,我的上下文(使用已购买插件的Magento 2签出)不允许我实现有效的视图模型,因此最终我设法通过简单的技巧解决了问题,添加了第二个输入类型=“ radio”,并在单击时显示: / p>

selectRadioPayment: function (obj, event, method) {
        this.selectPaymentMethod(obj, event, method);
        $('.ko-payment-selector').show();
        $('#p_method_' + method).hide();
        $('#p_method_' + method).closest('.radio-payment-selector').show();
    },

    renderedPaymentMethods: function() {
        if(quote.paymentMethod) {
            var selectedMethod = quote.paymentMethod().method;
            $('#p_method_' + selectedMethod).hide();
            $('#p_method_' + selectedMethod).closest('.radio-payment-selector').show();
        }
    },

    <input class="radio-payment-selector" type="radio" class="hidden" checked />
    <input class="ko-payment-selector" type="radio" name="payment[method]" class="radio" event: {change: function(data, event){$parent.selectRadioPayment(data, event, $data.method)}}"/>

我希望有一天能对某人有所帮助。