使用JavaScript确认框的Knockout点击绑定

14

我无法想出如何创建一个Knockout点击绑定,除非JavaScript确认对话框返回true,否则不执行valueAccessor。

它可能看起来像这样:

<a data-bind="confirmClick: { message: 'Are you sure?', click: someMethod }">Confirmable link</a>

在内部,confirmClick 绑定将执行类似以下的操作:

if (confirm(message)) {
   click();
}

我知道我可以通过将confirm(...)代码放在我的viewModel中来避免这样做,但那似乎不是放置这种代码的适当位置。我可能还可以使用jQueryUI或Bootstrap完成这种确认对话框,但我希望能够将其直接应用于任何项目中。

我已经在互联网上搜索了很久,但没有找到什么有用的信息... 我甚至查看了knockout的click事件的源代码(https://github.com/knockout/knockout/blob/master/src/binding/defaultBindings/event.js),但它看起来并不友好...

非常感谢任何形式的帮助!

2个回答

24
您需要创建自定义的 confirmClick 绑定处理程序,它接受您的消息和单击处理程序,并围绕确认逻辑进行封装。
ko.bindingHandlers.confirmClick = {
    init: function(element, valueAccessor, allBindings, viewModel) {
        var value = valueAccessor();
        var message = ko.unwrap(value.message);
        var click = value.click;
        ko.applyBindingsToNode(element, { click: function () {
            if (confirm(message))
                return click.apply(this, Array.prototype.slice.apply(arguments));
        }}, viewModel);
    }
}

你可以按照你所描述的方式使用它:

<a data-bind="confirmClick: { message: 'Are you sure?', click: someMethod }">
    Confirmable link</a>

示例 JSFiddle

注意:仅当您想要保留并传递原始的click事件处理程序参数到自己的单击事件处理程序时,才需要使用click.apply魔法。


最后确定一下……如果 confirm 返回 false,匿名的 click:function() { ....} 应该返回什么? - Alex Dresko
它将返回 undefined,因此 KO 不会调用您的处理程序,也不会执行浏览器操作(点击链接)。但是您可以根据自己的需要进行更改。 - nemesv
在另一个答案出现之前,我已经测试过这个方法,它非常有效。我很高兴花时间自己研究如何做到这一点,但我没有接近这种境界。谢谢! - Alex Dresko
2
好的回答,你的代码有一个小错误。init的第三个参数是allBindings而不是viewModel。你的JSFiddle能够工作是因为你在最终方法中没有使用vm参数。 - Michael
如果您需要在单击事件中使用viewModel,可以将其传递给click.apply函数。像这样:http://jsfiddle.net/L2Lrjdba/17/ - Onosa

0

我相信这就是Knockout定义点击绑定处理程序的地方 -

ko.bindingHandlers[eventName] = {
    'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var newValueAccessor = function () {
            var result = {};
            result[eventName] = valueAccessor();
            return result;
        };
        return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindings, viewModel, bindingContext);
    }
}

当eventName为'click'时,绑定处理程序。我相信将其放置在视图模型中或在Knockout加载后的某个位置应该可以解决问题 -

ko.bindingHandlers.clickConfirm = {
    'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var newValueAccessor = function () {
            var result = {};
            result.click = function () {
             var result = confirm('You are about to confirm something.');
                // If they press OK,
                console.log('pressed - ', result);
                if (result === true) {
                    console.log('Calling this - ', valueAccessor());
                    valueAccessor()();
                }

            }
            return result;
        };
        return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindings, viewModel, bindingContext);
    }
}

http://jsfiddle.net/XhLKD/


恭喜你找到了可行的解决方案,但是@nemesv的答案先到且有效,而且看起来更简单一些。我应该指出,在你们两个的解决方案中都有一些我无法理解的东西,所以从技术角度来看,你的答案可能更好。最终,基于我的无知,我选择了第一个、较短的答案。 - Alex Dresko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接