Knockout custom binding update function not firing

2020-06-13 10:34发布

I have a custom knockout binding that animates a toggle switch to an 'on' or 'off' position. My problem is the update function only fires immediately after the init and not when the observable value changes. Any ideas what I'm doing wrong?

ko.bindingHandlers.toggleSwitch = {

    init: function (element, valueAccessor) {
        var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor());
        var value = valueUnwrapped.value;
        var target = $(element);
        var disabled = valueAccessor().disabled;

        var id = 'ul' + (++ko.bindingHandlers['uniqueId'].currentIndex);
        var html = ['<div class="switch-mask"><ul id="' + id + '"', 'class="on-off-switch">', '<li class="on-switch">' + valueAccessor().on + '</li>', '<li class="on-off-knob"></li>', '<li class="off-switch">' + valueAccessor().off + '</li>', '</ul></div>'].join('');

        target.replaceWith(html);

        var mainTarget = $('#' + id);
        if (value()) {
            mainTarget.children('.on-switch').animate({ 'margin-left': '0px' });
            mainTarget.children('.on-off-knob').animate({ 'margin-left': '0px' });
        }
        else {
            mainTarget.children('.on-switch').animate({ 'margin-left': '-28px' });
            mainTarget.children('.on-off-knob').animate({ 'margin-left': '-1px' });
        };

        if (!disabled) {
            mainTarget.on('click', function() {
                //this fires every time the toggle switch is clicked.
                var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor());
                if (value()) {
                    mainTarget.children('.on-switch').animate({ 'margin-left': '0px' });
                    mainTarget.children('.on-off-knob').animate({ 'margin-left': '0px' });
                    value(false);
                } else {
                    mainTarget.children('.on-switch').animate({ 'margin-left': '-28px' });
                    mainTarget.children('.on-off-knob').animate({ 'margin-left': '-1px' });
                    value(true);
                }

                value.valueHasMutated();
            }); 
        }
    },
    update: function (element, valueAccessor) {
        var value = valueAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor());
        console.log('update called');
    }
};

ko.virtualElements.allowedBindings.toggleSwitch = true;

This is my binding:

<!-- ko toggleSwitch:{value:data.model.Settings.HtmlEmail,on:'On',off:'Off'}-->
<!-- /ko -->

标签: knockout.js
1条回答
Evening l夕情丶
2楼-- · 2020-06-13 10:59

The update event is not being fired because you're not binding directly to the observable, but to an object containing a property named value set to the observable. How I've accomplished this in the past is to omit the update function on the custom binding and just set a subscription on the observable in the in the init function, like this:

ko.bindingHandlers.toggleSwitch = {

  init: function (element, valueAccessor) {
    var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor());
    var value = valueUnwrapped.value;

   /// logic omitted for clarity

    value.subscribe(function(newValue) {
        console.log('update called');
    });

    if (!disabled) {
       /// omitted for clarity
    }
  }
};
查看更多
登录 后发表回答