Kyeotic
Kyeotic

Reputation: 19867

Knockout Binding doesn't init, starts with update

I have these two bindings that use the same init code, and are bound to the same value, but they don't init the same. The first behaves normally, the second one runs its update instead of init. Here are the bindings:

    function initToggle(element, valueAccessor) {
    // Initially set the element to be instantly visible/hidden depending on the value
    var value = valueAccessor();
    $(element).toggle(ko.utils.unwrapObservable(value)); // Use "unwrapObservable" so we can handle values that may or may not be observable
};

//Binding Handlers
ko.bindingHandlers.fadeVisible = {
    init: initToggle,
    update: function (element, valueAccessor) {
        // Whenever the value subsequently changes, slowly fade the element in or out
        var value = valueAccessor();
        ko.utils.unwrapObservable(value) ? $(element).fadeIn() : $(element).fadeOut();
    }
};

ko.bindingHandlers.slideVisibleVertical = {
    init: initToggle,
    update: function(element, valueAccessor, allBindingsAccessor) {        
        var value = valueAccessor(); //Lastest binding value
        var allBindings = allBindingsAccessor(); //other bindings, allows options

        var valueUnwrapped = ko.utils.unwrapObservable(value); 
        var duration = allBindings.slideDuration || 400; // 400ms is default duration unless otherwise specified

        if (valueUnwrapped == true)
             $(element).show('slide', {direction: 'up'}, duration);
        else
            $(element).hide('slide', {direction: 'up'}, duration);
    }
};

Literally, same init function. Here is a fiddle showing two buttons, both bound to the same value. fadeVisible starts out as shown, but slidevisibleVertical slides in. Both animate when updating. Anyone know whats going on here?

Upvotes: 3

Views: 1934

Answers (2)

kevinpo
kevinpo

Reputation: 1963

To clarify the accepted answer's comment about storing something on the element ($data), here is sample code:

ko.bindingHandlers.myHandler = {
    init: function (element, valueAccessor) {
        $(element).data("isFirstPass", true);
    },
    update: function (element, valueAccessor) {
        // Always unwrap so that ko tracks the dependency
        ko.unwrap(valueAccessor());

        if ($(element).data("isFirstPass")) {
            $(element).removeData("isFirstPass")
        }
        else {
            // Do something cool
        }
    }
};

Upvotes: 1

RP Niemeyer
RP Niemeyer

Reputation: 114792

The update function always runs the first time as well.

For your fadeVisible the element will already be visible, so fading it in will not do anything.

For the other binding calling slide on it will still animate it, even though it is shown.

Some different ways that you could handle it:

  • store something on the element ($data) to indicate that you are on the first pass and clear it as the end of the update (or vice-versa)
  • check the visibility before sliding (as you mentioned in the comments)

Upvotes: 4

Related Questions