Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply visible binding progmatically with knockout

I am writing a custom binding but as part of it I need to apply a data bind for the visible binding via javascript. There seems to be little problem in getting it to work up front, however when the observable being used is updated the binding does not get re-evaluated.

Upon looking in the source code for KO there is no init event so not sure if some space magic happens at some layer to get it to re-evaluate the dom elements on the observable changing but I am unable to find this info.

So is there some specific way to create an artificial binding which re-evaluates, or do I need to create my own subscribe callback to keep re-evaluating the visible binding?

Here is the code I am using:

ko.bindingHandlers.visible.update(element, isVisibleObservable, allBindingsAccessor, viewModel);

I know I could write my own show and hide logic, but I just thought it would be simpler on first glance to use the existing binding which does it under the hood.

Here is a simple example of the scenario with the code usage:

ko.bindingHandlers.someCustomBinding = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
        var allBindings = allBindingsAccessor();
        var customBindings = allBindings.someCustomBinding;
        var someReferencedElement = $(customBindings.target)[0];

        var isVisible = (customBindings.isDefault) ? true : false;
        var visibleObservable = ko.observable(isVisible);
        knockout.bindingHandlers.visible.update(someReferencedElement, visibleObservable, allBindingsAccessor, viewModel);

        element.onclick = function() { 
            var toggledValue = !visibleObservable();
            visibleObservable(toggledValue) 
        };
    }
};

I have heavily simplified the scenario, so removed validation of parameters etc but that should highlight the main usage and issue. When I click on the element with the custom binding it is toggling the value (as I can see this in the debugger) although it does not update the visibility of the referenced DOM element.

like image 400
Grofit Avatar asked Jan 22 '26 14:01

Grofit


1 Answers

The visible binding update function needs to be called from your update function or it will not function correctly. Just create an update function and move the call. Also, the 2nd argument is a valueAccessor, not the raw observable:

ko.bindingHandlers.someCustomBinding = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
        var allBindings = allBindingsAccessor();
        var customBindings = allBindings.someCustomBinding;
        var someReferencedElement = $(customBindings.target)[0];

        var isVisible = (customBindings.isDefault) ? true : false;
        var visibleObservable = ko.observable(isVisible);
        var visibleValueAccessor = function () { return visibleObservable; };

        // store the stuff as data on the element so that
        // it can be found in the update call
        var data = { element: somereferencedElement, v: visibleValueAccessor };
        ko.utils.domData.set(element, "__customBinding", data);

        element.onclick = function() { 
            var toggledValue = !visibleObservable();
            visibleObservable(toggledValue) 
        };
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
        var data = ko.utils.domData.get(element, "__customBinding");
        knockout.bindingHandlers.visible.update(data.element, data.v, allBindingsAccessor, viewModel);
    }
};
like image 188
Brandon Avatar answered Jan 25 '26 02:01

Brandon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!