Привязка клика нокаутом с подтверждением JavaScript

Я не могу понять, как создать привязку щелчка для выбивки, которая не выполняет valueAccessor, если диалоговое окно подтверждения JavaScript не вернет true.

Вероятно, это выглядит примерно так:

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

Внутри привязка verifyClick будет выглядеть примерно так:

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

Я знаю, что смогу обойти это, вставив код confirm(...) в мой viewModel, но это не похоже на подходящее место для размещения такого рода кода. Я мог бы также пойти так далеко, чтобы сделать этот вид диалога подтверждения с jQueryUI или Bootstrap, но я хочу кое-что, что я мог бы просто вставить в любой проект.

Я безуспешно отыскивал интернет-сети... Я даже посмотрел исходный код события щелчка для нокаута (https://github.com/knockout/knockout/blob/master/src/binding/defaultBindings/event.js), но он совсем не выглядит дружелюбным...

Любая помощь будет принята с благодарностью!

Ответ 1

Вам необходимо создать свой собственный 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.apply нужна вам только в том случае, если вы хотите сохранить и передать исходные аргументы обработчика событий click своему собственному обработчику событий щелчка.

Ответ 2

Я считаю, что именно здесь 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 - это "щелчок" для этого обработчика привязки. Я считаю, что размещение этого где-то в вашей модели представления или после загрузки 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/