javascript Knockout.js 和禁用锚标记
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10820122/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
knockout.js and disabling anchor tag
提问by Mike Flynn
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.
如何使用此自定义绑定禁用和启用锚标记。它适用于输入元素,但锚标记只是改变了 CSS,而不是禁用。
<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);
}
};
采纳答案by Artem
You need to capture click event in your binding handler.
您需要在绑定处理程序中捕获单击事件。
HTML:
HTML:
<a href="link" data-bind="disableClick: !enabled()">test</a>
<br/><br/><br/>
<input type="checkbox" data-bind="checked: enabled"> enabled ?
JavaScript:
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:
这是一个工作示例:
UPDATE 1: If you need to prevent other event handlers bound after knockout binding handler was attached, you need to add stopImmediatePropagationto the event handler along with preventDefault.
更新1:如果你需要防止挖空结合处理程序连接后必然其它事件处理程序,你需要添加stopImmediatePropagation到事件处理程序与一起preventDefault。
example: http://jsfiddle.net/kp74u/55/
示例: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):
更新 2:如果您想禁用所有事件处理程序(以及在绑定处理程序之前附加的单击事件处理程序,您需要“破解”jquery 事件数组)。请注意,这可能不适用于其他版本的 jquery(示例使用 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/
示例: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:
更新 3:正如那里提到的(FIR55TORM 建议的编辑,抱歉不能批准这个完全正确的编辑,因为我来不及):如果您使用的是 jQuery 1.10.x,则需要添加下划线才能访问“数据”对象像这样:
var events = $._data(element, "events");
Revised fiddle for jQuery 1.10.x: http://jsfiddle.net/nickolsky/kp74u/41/
jQuery 1.10.x 的修正小提琴:http: //jsfiddle.net/nickolsky/kp74u/41/
回答by Anders
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/
它与本机单击和启用绑定无缝连接(未实现禁用绑定) Fiddle(Fiddle 也使用我的约定而不是配置库) http://jsfiddle.net/xCfQC/30/
回答by Edyn
Using @Anders answer as inspiration, I came up with my own version of this. Allows for use of "enable", "disable" with or without the "click". Also allows for a custom disabled class, otherwise defaults to "disabled".
使用@Anders 的回答作为灵感,我想出了我自己的版本。允许使用“启用”、“禁用”,有或没有“点击”。还允许自定义禁用类,否则默认为“禁用”。
var koEnableUpdateOrig = ko.bindingHandlers.enable.update;
ko.bindingHandlers.enable.update = function (element, valueAccessor, allBindings) {
// call original enable update
var result = koEnableUpdateOrig.apply(this, arguments);
var enabled = ko.unwrap(valueAccessor());
// get and apply disabled class
var disabledClass = "disabled";
if (allBindings)
disabledClass = allBindings().disabledClass || "disabled";
if (enabled) {
$(element).removeClass(disabledClass);
if (element.tagName === "A")
$(element).off("click.koEnableUpdate");
}
else {
$(element).addClass(disabledClass);
if (element.tagName === "A")
$(element).on("click.koEnableUpdate", function (e) { e.preventDefault(); });
}
return result;
};
ko.bindingHandlers.disable.update = function (element, valueAccessor, allBindings) {
// call enable with the reverse value
// the original knockout disable does this, but does not pass the allBindings
ko.bindingHandlers.enable.update(element, function () {
return !ko.unwrap(valueAccessor())
}, allBindings);
};
var koClickInitOrig = ko.bindingHandlers.click.init;
ko.bindingHandlers.click.init = function (element, valueAccessor, allBindings) {
// wrap click function with enable/disable check
var valueAccessorOrig = valueAccessor();
valueAccessor = function () {
return function () {
if (ko.unwrap(allBindings().enable) ||
(allBindings().disable == null || !ko.unwrap(allBindings().disable))) {
valueAccessorOrig.apply(this, arguments);
}
}
};
// apply wrapped click to original click init
koClickInitOrig.apply(this, arguments);
};
回答by mikilion
This is my approach:
这是我的方法:
JavaScript
JavaScript
(function () {
var originalDisableUpdate = ko.bindingHandlers.disable.update;
ko.bindingHandlers.disable.update = function (element, valueAccessor) {
if (element.tagName === 'A') {
var
value = ko.utils.unwrapObservable(valueAccessor()),
disabled = 'disabled';
if (value) {
element.setAttribute(disabled, null);
}
else {
element.removeAttribute(disabled);
}
}
else {
originalDisableUpdate(element, valueAccessor);
}
};
})();
CSS
CSS
a[disabled] {
pointer-events:none;
cursor:default;
}

