web-dev-qa-db-fra.com

<input> événement lostfocus / onblur en knockout

Je veux exécuter un événement sur un observable knockout lié à un input. Cette fonction doit être exécutée lorsque le contrôle perd le focus, même sans rien taper. J'ai essayé de modifier la liaison d'événement, mais elle ne se déclenche pas lorsque l'utilisateur s'éloigne du contrôle sans rien taper. J'ai essayé l'événement mouseout, mais cela ne se déclenche que lorsque l'utilisateur clique ailleurs dans le formulaire, après avoir perdu le focus - pas exactement ce que je veux. Je veux que le pair se déclenche dès que la mise au point est éloignée du contrôle, même avec la tabulation.

Voici le code que j'ai utilisé pour l'événement 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');
    }
}

Quelqu'un peut-il aider s'il vous plaît?

26
devC

Je pense qu'il y a quelques approches que vous pourriez utiliser. Une bonne option serait d'utiliser la liaison hasfocus de KO: http://knockoutjs.com/documentation/hasfocus-binding.html .

Vous pouvez vous lier à un booléen observable, puis vous y abonner. Dans l'abonnement, vous pouvez choisir de ne réagir que lorsque la valeur est désormais fausse.

Quelque chose comme:

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
   }
});

Liez-le comme:

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

Je pense que ce serait une bonne option si vous voulez qu'il se déclenche chaque fois qu'un utilisateur quitte le champ, quelle que soit la façon dont il le quitte et indépendamment du fait qu'un changement ait été réellement effectué.

32
RP Niemeyer

J'aime la réponse de @ RPNiemeyer. Cependant, je voulais juste souligner que tout tout ne doit pas être fait via Knockout. C'est juste un outil, et parfois ce n'est pas le meilleur outil pour le travail. Vous devez toujours utiliser une liaison d'événement directe comme vous l'avez toujours fait dans JS, c'est-à-dire.

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

Si vous devez réellement interagir avec votre modèle de vue, vous pouvez simplement utiliser ko.dataFor comme décrit dans le documentation de Knockout sur la délégation d'événement :

$('#FirstName').on('blur', function () {
    var data = ko.dataFor(this);
    // do something with data, i.e. data.FirstName()
});
22
Chris Pratt

Cela a fonctionné pour moi:

data-bind="event: { blur: OnBlurEvent }"
19
arntjw

Je viens d'avoir le même problème, je l'ai résolu en créant une liaison personnalisée:

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

Et puis je l'ai appelé comme ceci:

 data-bind="value: FirstName, modifyOnFocusOut: FirstName"
5
jfc37

As-tu essayé event:{blur: ValidateFirstName} cet événement sera déclenché si l'utilisateur clique ou "tabule" l'entrée.

<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}"

Voici un JSFiddle d'un exemple de travail.

4
Gab

En utilisant TypeScript, je l'ai résolu en utilisant 2 liaisons personnalisées, une SetFocusBinding et une OnBlur Binding ... En utilisant la SetFocusBinding, je m'assure que le champ d'entrée a le focus. À l'aide de la liaison OnBlur, une fonction est appelée lorsque l'événement flou est déclenché.

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();
        }
    }
}

et ...

    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();
0
Paul0515