2012-05-30 65 views
12

如何禁用并启用具有此定制绑定的定位标记。它对输入元素非常有用,但是锚点标签只是改变了CSS,而不是禁用。knockout.js并禁用定位标记

<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); 
    } 
}; 
+0

我只是通过他们的点击数设置为可见锚标记 “已禁用”假。你的意思是什么意思是要发生在主播“禁用”它? – Tyrsius

+0

只是为了确保它不触发任何点击事件,并且启用时,点击事件是可修改的。 –

+1

作为一种替代方法,您可以使用KO注释逻辑来生成不同的标签。请参阅:http://stackoverflow.com/q/15969045/52551 –

回答

11

您需要在绑定处理程序中捕获单击事件。

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)}); 

这里是一个工作示例:

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

更新1:如果您需要防止挖空结合处理程序连接后必然其它事件处理程序,您需要添加stopImmediatePropagation到事件处理程序与preventDefault一起。

例如:http://jsfiddle.net/kp74u/55/

更新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 
      }; 
     }); 
    } 
}; 

例如:http://jsfiddle.net/nickolsky/kp74u/40/

更新3:正如有提到(suggested edit by FIR55TORM,对不起,不能完全同意这个正确的编辑,因为我来不及审查):如果你使用jQuery 1.10.x,你将需要添加下划线来访问“数据”对象,像这样:

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

修订捣鼓jQuery的1.10.x:http://jsfiddle.net/nickolsky/kp74u/41/

+0

这是否停止其他点击事件? http://jsfiddle.net/kp74u/3/ –

+0

我添加了关于禁用所有单击事件的更新 – Artem

+0

从jQuery 1.8开始,您不能再通过该API访问数据。替换为'jQuery._data(key,value)' –

1

我发现这个答案goggling这样做的一种方式时,但我不喜欢这样的方式做了我自己的

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); 
}; 

无缝的与本地点击并启用绑定(禁用绑定未实现) 小提琴(小提琴也使用我的约定优于配置库) http://jsfiddle.net/xCfQC/30/

+0

真的很喜欢这个想法,主要缺点是你必须定义一个“点击”方法才能工作。查看我的答案,找出解决方法,无论是否定义点击。 – Edyn

0

使用@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); 
}; 
+0

当你想在没有点击处理程序的情况下启用/禁用时,无法真正看到用例:D这里是一个支持禁用的版本http://jsfiddle.net/xCfQC/31/ – Anders

+1

@Anders当你有一个集合href的锚点并且没有需要点击。那是我的情况。 – Edyn

+0

但href仍然会执行,它唯一的CSS?你需要从点击处理程序返回false以防止它触发,你可以在你的包装器clikc处理程序 – Anders

0

这是我的方法:

的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

a[disabled] { 
    pointer-events:none; 
    cursor:default; 
}