我如何获得Knockout Click绑定以尊重非表单元素上的Knockout Enable绑定?

时间:2013-05-14 17:35:55

标签: knockout.js

我有一个<span>,上面有几个绑定。 enableclick

<span data-bind="enable: buttonEnabled, click: takeAnAction">Take An Action</span>

我可以写一个自定义绑定处理程序,或者当click绑定为false时,是否有另一种简单的方法让enable绑定尊重(而不是行动)?

我知道我可以在if操作中添加click语句,但如果我可以自动执行此操作而不在我的视图中添加额外的逻辑,那就太棒了。

3 个答案:

答案 0 :(得分:2)

您似乎从评论中更新了问题。如果您使用支持被禁用的按钮或输入元素,那么这将自然适合您。

如果您确实需要使用类似span的内容,那么您可以编写一个快速自定义绑定,将其包装在条件检查中:

ko.bindingHandlers.clickIf = {
    init: function(element, valueAccessor) {
       var options = ko.utils.unwrapObservable(valueAccessor()),
           wrappedHandler;

        if (options && options.condition && typeof options.action === "function") {
            wrappedHandler = function(data, event) {
               if (ko.utils.unwrapObservable(options.condition)) {
                  options.action.call(data, data, event);
               }
           };

           ko.applyBindingsToNode(element, { click: wrappedHandler });  
        }     
    }
};

您可以使用它:

<span data-bind="clickIf: { action: test, condition: isEnabled }">Test</span>

示例:http://jsfiddle.net/rniemeyer/LZTtE/

答案 1 :(得分:1)

RP Niemeyer's answer为基础。一个更简单(但不易扩展的解决方案)是直接在自定义绑定处理程序中引用元素enable属性。

ko.bindingHandlers.clickIfEnabled = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var action = ko.utils.unwrapObservable(valueAccessor()),
            wrappedHandler = function(data, event) {
               if (allBindingsAccessor().enable()) {
                  action.call(data, data, event);
               }
            };

        ko.applyBindingsToNode(element, { click: wrappedHandler });        
    }
};

像这样使用:

<span data-bind="enable: isEnabled, clickIfEnabled: test">Test</span>

此方法仅允许您更改一个标准绑定。 clickclickIfEnabled

示例:http://jsfiddle.net/LZTtE/6/

答案 2 :(得分:0)

RP Niemeyer的答案是一个可扩展解决方案的良好开端。但是,它不允许您在'condition'选项中包含一个包含observables 的表达式,当这些observable随时间变化时会被重新评估。

例如,此绑定仅评估'condition'表达式一次(执行init回调时),并且当observables的值发生更改时无法正常工作:

<span data-bind="clickIf: { action: doSomething, condition: (isEnabled() == true && anotherObservable() == true) }">Test</span>

为了使此绑定接受包含observable的表达式,并根据该表达式的最新值正确执行,您需要重构绑定处理程序,如下所示:< /强>

ko.bindingHandlers.clickIf = {

    init: function (element, valueAccessor) {        
        // Hold state of options so that the 'update' callback can effectively 
        // 'pass in' new evaluated 'condition' expressions (as observables change) to the wrappedHandler.
        element.ko_clickIfOptions = ko.utils.unwrapObservable(valueAccessor());

        var wrappedHandler = function (data, event) {
            // "ko_clickIfOptions.condition" will get us the current value of a 'condition'
            //   expression since the 'update' callback updates these options            
            var condition = ko.utils.unwrapObservable(element.ko_clickIfOptions.condition);
            if (condition) {                
                element.ko_clickIfOptions.action.call(data, data, event);
            }
        };
        ko.applyBindingsToNode(element, { click: wrappedHandler });
    },
    // When the value of any observable in your expression changes, we grab 'options' 
    // again so that the wrappedHandler will have the latest value of the expression
    update: function (element, valueAccessor) {        
        element.ko_clickIfOptions = ko.utils.unwrapObservable(valueAccessor());
    }
};

通过此实现,即使“条件”表达式中的任何可观察对象发生更改,上面列出的示例也能正常运行。