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);
}
};
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/
I found this answer when goggling for a way of doing this, but I didn't like the approach so did my own
var orgClickInit = ko.bindingHandlers.click.init;
ko.bindingHandlers.click.init = function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (element.tagName === "A" && allBindingsAccessor().enable != null) {
var disabled = ko.computed(function () {
return ko.utils.unwrapObservable(allBindingsAccessor().enable) === false;
});
ko.applyBindingsToNode(element, { css: { disabled: disabled} });
var handler = valueAccessor();
valueAccessor = function () {
return function () {
if (ko.utils.unwrapObservable(allBindingsAccessor().enable)) {
handler.apply(this, arguments);
}
}
};
}
orgClickInit(element, valueAccessor, allBindingsAccessor, viewModel);
};
Its seamless with the native click and enable binding (disable binding not implemented) Fiddle (Fiddle also uses my Convention over configuration library) http://jsfiddle.net/xCfQC/30/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With