jtabuloc
jtabuloc

Reputation: 2535

Is it necessary to unbind/off JQuery click event inside Knockout custom binding?

Given the scenario below is it necessary to unbind click event inside custom binding handler init using ko.utils.domNodeDisposal.addDisposeCallback? Or does Knockout has it's own mechanism to automatically dispose/unbind event created inside custom binding handler?

Example :

<li>
   <a id='aTagId' data-bind='something'></a>
   <button data-bind: myCustomBinding:{}>       
</li>

ko.bindingHandlers.myCustomBinding=
{
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext)
    {
        $('#aTagId').on('click', function() { /*something in here*/ });

        // Is this code necessary?      
        ko.utils.domNodeDisposal.addDisposeCallback(element, function ()
        {
            $('#aTagId').off('click');
        });
    }
}

Note : Please don't ask me why I can't just put myCustomBinding in <a> tag :)

Upvotes: 1

Views: 315

Answers (1)

yurzui
yurzui

Reputation: 214007

I guess it makes sense for event handlers attached to long-living objects(window, document etc):

ko.bindingHandlers.myBinding = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var handler = function () {};

        $(window).on("resize", handler);

        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(window).off("resize", handler);
        });
    })
};

See also - http://www.knockmeout.net/2014/10/knockout-cleaning-up.html

But in your scenario

Firstly your element is already removed when you're trying to call off:

ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
   $('#aTagId').off('click'); //<== $('#aTagId').length is 0
});

You can rewrite it as follows:

var $aTag = $('#aTagId').on('click', function() {});

ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
 $aTag.off('click');
});

But secondly knockout has it's own mechanism to automatically dispose/unbind event. It's running jQuery.cleanData

// Perform cleanup needed by external libraries (currently only jQuery, but can be extended)
ko.utils.domNodeDisposal["cleanExternalData"](node);

...
"cleanExternalData" : function (node) {
   // Special support for jQuery here because it's so commonly used.
   // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
   // so notify it to tear down any resources associated with the node & descendants here.
   if (jQueryInstance && (typeof jQueryInstance['cleanData'] == "function"))
     jQueryInstance['cleanData']([node]);
}

https://github.com/knockout/knockout/blob/241c26ca82e6e4b3eaee39e3dc0a92f85bc1df0c/src/utils.domNodeDisposal.js#L88-L94

This way your handler will be automatically disposed

enter image description here

Upvotes: 0

Related Questions