knockout.js and disabling anchor tag

anchor, javascript, knockout.js

Solution

You need to capture click event in your binding handler.

HTML:

<a href="link" data-bind="disableClick: !enabled()">test</a>
<br/><br/><br/>
<input type="checkbox" data-bind="checked: enabled"> enabled ​

JavaScript:

ko.bindingHandlers.disableClick = {
    init: function (element, valueAccessor) {

        $(element).click(function(evt) {
            if(valueAccessor())
                evt.preventDefault();
        });

    },

    update: function(element, valueAccessor) {        
        var value = ko.utils.unwrapObservable(valueAccessor());
        ko.bindingHandlers.css.update(element, function() {return { disabled_anchor: value }; });
    }
};

ko.applyBindings({ enabled: ko.observable(false)});

Here is a working example:

http://jsfiddle.net/kp74u/54/

UPDATE 1: If you need to prevent other event handlers bound after knockout binding handler was attached, you need to add `stopImmediatePropagation` to the event handler along with `preventDefault`.

example: http://jsfiddle.net/kp74u/55/

UPDATE 2: If you want to disable all event handlers (along with click event handlers attached before your binding handler, you need to 'hack' the jquery events array). Please note that this may not work other versions of jquery (example uses 1.7):

ko.bindingHandlers.disableClick = {
    init: function(element, valueAccessor) {

        $(element).click(function(evt) {
            alert('test before');
        });

        $(element).click(function(evt) {
            if (valueAccessor()) {
                evt.preventDefault();
                evt.stopImmediatePropagation();
            }
        });

        //begin of 'hack' to move our 'disable' event handler to top of the stack
        var events = $.data(element, "events");
        console.log(events);
        var handlers = events['click'];

        if (handlers.length == 1) {
            return;
        }

        handlers.splice(0, 0, handlers.pop());
        //end of 'hack' to move our 'disable' event handler to top of the stack


        $(element).click(function(evt) {
            alert('test after');
        });
    },

    update: function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        ko.bindingHandlers.css.update(element, function() {
            return {
                disabled_anchor: value
            };
        });
    }
};

example: http://jsfiddle.net/nickolsky/kp74u/40/

UPDATE 3: As was mentioned there (suggested edit by FIR55TORM, sorry can't approve this completely correct edit because I am too late to review): if you're using jQuery 1.10.x, you will need to add an underscore to access the 'data' object like so:

var events = $._data(element, "events"); 

Revised fiddle for jQuery 1.10.x: http://jsfiddle.net/nickolsky/kp74u/41/

Problem

How can I disable and enable an anchor tag with this custom binding. It works great with input elements but the anchor tag just changes the CSS, not the disabling. ``` <a href="link" data-bind="myDisabled: !enabled()"/> ko.bindingHandlers.myDisabled = { update: function(element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); ko.bindingHandlers.css.update(element, function() {return { disabled: value }; }); ko.bindingHandlers.disable.update(element, valueAccessor); } }; ```

Original source

Related problems