Пользовательское возвращаемое значение bindingHandler / наблюдаемый

Я не смог найти решение для этого.

Я пытаюсь создать пользовательский bindingHandler для события click по тегу div элемента html.

// custom bindingHandler and observable
<div data-bind="OnClickEvent: HasBeenClicked"></div>
// to show observable's true/false value
<span data-bind="text: 'Observable: ' + HasBeenClicked()"></span>

Этот bindingHandler делает то, что должен, если вы нажмете на div, текст изменится. Однако наблюдаемое говорит, что если ложно.

ko.bindingHandlers.OnClickEvent = {
    update: function (element, valueAccessor) {

        $(element).text('Click Here: false');

        var observable = ko.utils.unwrapObservable(valueAccessor());

        $(element).on('click', function () {

            observable = !observable;

            if (observable) {
                $(element).text('Click Here: true');
            } else {
                $(element).text('Click Here: false');
            }
        });
    }
}


function ViewModel() {
    var self = this;
    self.HasBeenClicked = ko.observable(false);
}

ko.applyBindings(new ViewModel());

Как настроить наблюдаемый HasBeenClicked для переключения между истиной / ложью при каждом щелчке, как в тексте?

1 ответ

Решение

Второй комментарий @nemesv по поводу быстрого исправления, а также тот факт, что ваша привязка выглядит немного странно. Я расширю его до ответа, потому что мне нужна комната.

Сначала быстрое решение:

  • Я думаю, что для типа связывания, который вы пишете, более уместно делать свою работу внутри init часть;
  • Вы должны написать обратно в valueAccessor изменить значение наблюдаемой (я показываю быстрое и грязное демо ниже);

Вот рабочий пример:

ko.bindingHandlers.OnClickEvent = {
    init: function (element, valueAccessor) {

        $(element).text('Click Here: false');

        var observable = ko.utils.unwrapObservable(valueAccessor());
        
        $(element).on('click', function () {
            observable = !observable;
            
            valueAccessor()(observable);

            if (observable) {
                $(element).text('Click Here: true');
            } else {
                $(element).text('Click Here: false');
            }
        });
    }
}

function ViewModel() {
    var self = this;
    self.HasBeenClicked = ko.observable(false);
}

ko.applyBindings(new ViewModel());
div { padding: 10px; background-color: pink; margin-bottom: 10px; cursor: pointer; }
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<div data-bind="OnClickEvent: HasBeenClicked"></div>
<span data-bind="text: 'Observable: ' + HasBeenClicked()"></span>

Тем не менее, я думаю, что такое сочетание jQuery, обработки событий и Knockout довольно сомнительно. Вам следует подумать, не страдаете ли вы XY-проблемой, и не можете ли вы удовлетворить свои требования с помощью существующих обработчиков привязки. Вот один из способов сделать что-то похожее:

function ViewModel() {
    var self = this;
    self.HasBeenClicked = ko.observable(false);
    self.handleClick = function() {
      self.HasBeenClicked(!self.HasBeenClicked());
    };
}

ko.applyBindings(new ViewModel());
div { padding: 10px; background-color: pink; margin-bottom: 10px; cursor: pointer; }
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<div data-bind="click: handleClick, text: 'Click here: ' + HasBeenClicked()"></div>
<span data-bind="text: 'Observable: ' + HasBeenClicked()"></span>

Говоря о существующих обработчиках привязки, знайте, что есть click переплет, который может удовлетворить ваши потребности. Если это не так, я бы порекомендовал посмотреть на соответствующий источник (click перенаправляет на event связывание, смотрите этот файл в GitHub), чтобы черпать вдохновение для своего собственного обработчика.

Другие вопросы по тегам