Comment puis-je obtenir Knockout JS à data-bind sur keypress au lieu de lost-focus?

Cet exemple de knockout JS fonctionne ainsi lorsque vous modifiez un champ et appuyez sur TAB, les données viewmodel et donc le texte sous les champs sont mis à jour.

Comment puis-je changer ce code pour que les données viewmodel soient mises à jour à chaque pression de touche?

le texte d'alt

<!doctype html>
<html>
    <title>knockout js</title>
    <head>
        <script type="text/javascript" src="js/knockout-1.1.1.debug.js"></script>
        <script type="text/javascript">
        window.onload= function() {

            var viewModel = {
                firstName : ko.observable("Jim"),
                lastName : ko.observable("Smith")
            };
            viewModel.fullName = ko.dependentObservable(function () {
                return viewModel.firstName() + " " + viewModel.lastName();
            });

            ko.applyBindings(viewModel);
       }
        </script>
    </head>
    <body>
        <p>First name: <input data-bind="value: firstName" /></p>
        <p>Last name: <input data-bind="value: lastName" /></p>
        <h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
    </body>
</html>
184
demandé sur Shadow Wizard 2010-12-08 13:14:47

4 réponses

<body>
        <p>First name: <input data-bind="value: firstName, valueUpdate: 'afterkeydown'" /></p>
        <p>Last name: <input data-bind="value: lastName, valueUpdate: 'afterkeydown'" /></p>
        <h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
</body>

De la documentation

Paramètres Supplémentaires

  • ValueUpdate

    Si votre liaison inclut également un paramètre appelé valueUpdate, ceci définit l'Événement du navigateur KO à utiliser pour détecter les modifications. Le les valeurs de chaîne suivantes sont les choix les plus couramment utiles:

    • "modifier" (par défaut) - met à jour votre modèle de vue lorsque l'utilisateur déplace le focus vers un contrôle différent, ou dans le cas de éléments, immédiatement après tout changement

    • "keyup" - met à jour votre modèle de vue lorsque l'utilisateur libère une clé

    • "keypress" - met à jour votre modèle de vue lorsque l'Utilisateur a tapé un clé. Contrairement à keyup, cette mise à jour à plusieurs reprises pendant que l'utilisateur détient une clé vers le bas

    • "afterkeydown" - met à jour votre modèle de vue dès que l'utilisateur commence à taper un caractère. Cela fonctionne en attrapant le navigateur événement keydown et gestion de l'événement de manière asynchrone.

Parmi ces options, "afterkeydown" est le meilleur choix si vous voulez gardez votre modèle de vue mis à jour en temps réel.

294
répondu Sergei Golos 2017-05-08 13:49:00

Dans version 3.2, vous pouvez simplement utiliser textinput de liaison.:

<input data-bind="textInput: userName" />

, Il fait deux choses importantes:

  • faire des mises à jour immédiates
  • gère les différences de navigateur pour couper, glisser, saisie semi-automatique ...

Donc pas besoin de modules supplémentaires, de contrôles personnalisés et d'autres choses.

81
répondu Salvador Dali 2014-08-25 19:46:29

Si vous voulez qu'il fasse des mises à jour sur afterkeydown "par défaut", vous pouvez injecter la liaison valueUpdate dans le gestionnaire de liaison value. Il suffit de fournir un nouveau allBindingsAccessor pour le gestionnaire à utiliser qui inclut afterkeydown.

(function () {
    var valueHandler = ko.bindingHandlers.value;
    var getInjectValueUpdate = function (allBindingsAccessor) {
        var AFTERKEYDOWN = 'afterkeydown';
        return function () {
            var allBindings = ko.utils.extend({}, allBindingsAccessor()),
                valueUpdate = allBindings.valueUpdate;

            if (valueUpdate === undefined) {
                return ko.utils.extend(allBindings, { valueUpdate: AFTERKEYDOWN });
            } else if (typeof valueUpdate === 'string' && valueUpdate !== AFTERKEYDOWN) {
                return ko.utils.extend(allBindings, { valueUpdate: [valueUpdate, AFTERKEYDOWN] });
            } else if (typeof valueUpdate === 'array' && ko.utils.arrayIndexOf(valueUpdate, AFTERKEYDOWN) === -1) {
                valueUpdate = ko.utils.arrayPushAll([AFTERKEYDOWN], valueUpdate);
                return ko.utils.extend(allBindings, {valueUpdate: valueUpdate});
            }
            return allBindings;
        };
    };
    ko.bindingHandlers.value = {
        // only needed for init
        'init': function (element, valueAccessor, allBindingsAccessor) {
            allBindingsAccessor = getInjectValueUpdate(allBindingsAccessor);
            return valueHandler.init(element, valueAccessor, allBindingsAccessor);
        },
        'update': valueHandler.update
    };
} ());

Si vous n'êtes pas à l'aise de "remplacer" la liaison value, Vous pouvez donner un nom différent à la liaison personnalisée prioritaire et utiliser ce gestionnaire de liaison.

ko.bindingHandlers.realtimeValue = { 'init':..., 'update':... };

Démo

Une solution comme celle-ci serait appropriée pour Knockout version 2.X. L'équipe à élimination directe a étoffé une liaison plus complète pour les entrées de type texte à travers la liaison textInput dans Knockout version 3 et plus. Il a été conçu pour gérer toutes les méthodes de saisie de texte pour les entrées de texte et textarea. Il va même gérer la mise à jour en temps réel qui rend effectivement cette approche obsolète.

35
répondu Jeff Mercado 2014-11-14 16:34:42

La réponse de Jeff Mercado est fantastique, mais malheureusement cassé avec Knockout 3.

Mais j'ai trouvé la réponse suggérée par les développeurs ko tout en travaillant à travers les changements Knockout 3. Voir les commentaires du bas à https://github.com/knockout/knockout/pull/932 . leur code:

//automatically add valueUpdate="afterkeydown" on every value binding
(function () {
    var getInjectValueUpdate = function (allBindings) {
        return {
            has: function (bindingKey) {
                return (bindingKey == 'valueUpdate') || allBindings.has(bindingKey);
            },
            get: function (bindingKey) {
                var binding = allBindings.get(bindingKey);
                if (bindingKey == 'valueUpdate') {
                    binding = binding ? [].concat(binding, 'afterkeydown') : 'afterkeydown';
                }
                return binding;
            }
        };
    };

    var valueInitHandler = ko.bindingHandlers.value.init;
    ko.bindingHandlers.value.init = function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        return valueInitHandler(element, valueAccessor, getInjectValueUpdate(allBindings), viewModel, bindingContext);
    };
}());

Http://jsfiddle.net/mbest/GKJnt/

Modifier Ko 3.2.0 a maintenant une solution plus complète avec la nouvelle liaison "textInput". Voir la réponse de SalvidorDali

20
répondu RockResolve 2014-11-09 09:47:37