‹ввод› потеря фокуса/размытие в нокауте

Я хочу выполнить событие для наблюдаемого нокаута, связанного с input. Эта функция должна выполняться, когда элемент управления теряет фокус, даже если ничего не набирается. Я попытался изменить привязку события, но оно не срабатывает, когда пользователь уходит от элемента управления, ничего не набрав. Я пробовал событие mouseout, но оно срабатывает только тогда, когда пользователь щелкает в другом месте формы после потери фокуса - не совсем то, что я хочу. Я хочу, чтобы даже срабатывал, как только фокус перемещается от элемента управления, даже с вкладкой.

Ниже приведен код, который я использовал для события mouseout:

<input
    type="text"
    id="txtFirstName"
    tabindex="1"
    maxlength="25"
    class="txtbox" 
    style="width: 200px;"
    data-bind="value: FirstName, 
               attr: {title: FirstNameErrorMessage },
               css: {validationFailed: !IsValidFirstName() },
               event: {mouseout: ValidateFirstName}" 
/>

this.ValidateFirstName = function () {
    self.IsValidFirstName(true);
    self.FirstNameErrorMessage('');
    if (self.FirstName() == '') {
        self.IsValidFirstName(false);
        self.FirstNameErrorMessage('First Name is required');
    }
}

Кто-нибудь может помочь, пожалуйста?


person devC    schedule 19.04.2013    source источник


Ответы (6)


Я думаю, что есть несколько подходов, которые вы могли бы использовать. Неплохим вариантом было бы использовать привязку hasfocus KO: http://knockoutjs.com/documentation/hasfocus-binding.html.

Вы можете выполнить привязку к логическому наблюдаемому объекту, а затем подписаться на него. В подписке вы можете реагировать только тогда, когда значение теперь равно false.

Что-то вроде:

self.FirstName = ko.observable();
self.FirstName.focused = ko.observable();

self.FirstName.focused.subscribe(function(newValue) {
   if (!newValue) {
       //do validation logic here and set any validation observables as necessary
   }
});

Привяжите его, как:

data-bind="value: FirstName, hasfocus: FirstName.focused"

Я думаю, что это был бы хороший вариант, если вы хотите, чтобы он срабатывал каждый раз, когда пользователь покидает поле, независимо от того, как он покидает его и независимо от того, было ли действительно сделано изменение.

person RP Niemeyer    schedule 19.04.2013
comment
+1: OMG, я вырезал и взламывал фрагмент кода, который я написал почти так же. Я не мог на всю жизнь понять, что, черт возьми, отличалось, что сработало бы в вашем ответе, который я не написал сам. У меня было data-bind="text вместо data-bind="value для ввода. Спасибо за добавление заявления о привязке в ваш ответ. Сегодня мне нужен был этот пинок под зад. - person Joel Etherton; 16.06.2014
comment
@JoelEtherton - я сам точно не делал этого раз или два. Рад, что ты понял это. - person RP Niemeyer; 16.06.2014
comment
Я пробовал эту технику. Для меня проблема заключается в том, что hasFocus всегда срабатывает (превращается в true) при начальной загрузке страницы, что приводит все в неправильное состояние для того, что я пытаюсь сделать. Я инициализирую соответствующее значение модели представления значением false, но это ничего не изменило. - person Dave Munger; 09.07.2014
comment
Упс, только что понял, что ЛЮБОЕ изменение фокуса, включая потерю фокуса, приведет к изменению связанного значения. Поэтому мне просто нужно опросить newValue, чтобы узнать, является ли фокус истинным или ложным. Тот факт, что в нем есть имя события («фокус»), заставил меня забыть, как работают наблюдаемые. :) - person Dave Munger; 09.07.2014
comment
У меня проблемы с этим подходом. Я думаю, это потому, что у меня есть несколько полей ввода, привязанных к одному и тому же наблюдаемому. Что происходит, так это то, что вещь срабатывает четыре раза, а newValue переключается между true и false. Собираюсь просто использовать размытие jquery. - person Sean; 22.05.2015
comment
Если также срабатывает при начальной загрузке страницы, есть ли у кого-нибудь решение для этого? спасибо - person Yaron; 02.02.2018

Это сработало для меня:

data-bind="event: { blur: OnBlurEvent }"
person arntjw    schedule 20.08.2014
comment
Если это все, что вам нужно, я осмелюсь сказать, что это лучший способ. Интересно, что @rp-niemeyer думает об этом. Наверняка такой подход приходил ему в голову? - person aaaidan; 15.10.2014

Мне нравится ответ @RPNiemeyer. Однако я просто хотел указать, что не все нужно делать через Knockout. Это просто инструмент, и иногда это не лучший инструмент для работы. Вы всегда просто используете прямую привязку событий, как вы всегда делали в JS, т.е.

$('#FirstName').on('blur', function () {
    // do something
});

Если вам нужно на самом деле взаимодействовать с вашей моделью представления, вы можете просто использовать ko.dataFor, как описано в Документация Knockout по делегированию событий:

$('#FirstName').on('blur', function () {
    var data = ko.dataFor(this);
    // do something with data, i.e. data.FirstName()
});
person Chris Pratt    schedule 19.04.2013
comment
Мне это решение нравится немного больше, потому что оно не добавляет никаких подписок. :) - person Josh; 12.02.2015

У меня была такая же проблема, я решил ее, создав пользовательскую привязку:

ko.bindingHandlers.modifyOnFocusOut = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        $(element).blur(function() {
            //Do your work
        });
    }
}

А потом назвал это так:

 data-bind="value: FirstName, modifyOnFocusOut: FirstName"
person jfc37    schedule 14.07.2013

Пробовали ли вы event:{blur: ValidateFirstName}, это событие будет запущено, если пользователь щелкнет или «выйдет» из ввода.

<input
    type="text"
    id="txtFirstName"
    tabindex="1"
    maxlength="25"
    class="txtbox" 
    style="width: 200px;"
    data-bind="value: FirstName, 
               attr: {title: FirstNameErrorMessage},
               css: {validationFailed: !IsValidFirstName()},
               event: {blur: ValidateFirstName}"

Вот JSFiddle рабочего примера.

person Gab    schedule 25.10.2014

Используя TypeScript, я решил это с помощью двух пользовательских привязок: SetFocusBinding и OnBlur Binding... Используя SetFocusBinding, я удостоверился, что поле ввода имеет фокус. При использовании привязки OnBlur функция вызывается при запуске события размытия.

module Fx.Ko.Bindings {
    export class SetFocusBinding implements KnockoutBindingHandler {
        public update(element, valueAccessor, allBindingsAccessor) {
            var value = valueAccessor();
            var valueUnwrapped = ko.unwrap(value);
            if (valueUnwrapped == undefined) {
                return;
            }
            if (valueUnwrapped)
                $(element).focus();
        }
    }
}

и ...

    module Fx.Ko.Bindings {
        export class OnBlurBinding implements KnockoutBindingHandler {
            public init(element, valueAccessor, allBindings, viewModel, bindingContext) {
                var value = valueAccessor();
                $(element).on('blur', function (event) {
                    value();
                });
            }
        }
    }
interface KnockoutBindingHandlers {
    onBlur: KnockoutBindingHandler;
}
ko.bindingHandlers.onBlur = new Fx.Ko.Bindings.OnBlurBinding();
person Paul0515    schedule 16.06.2015