192 Stimmen

Wie kann ich Knockout JS zu Daten binden auf Tastendruck anstelle von verlorenen Fokus?

Dieses Beispiel von Knockout Js funktioniert so, dass, wenn Sie ein Feld bearbeiten und TAB drücken, die Daten des Ansichtsmodells und damit der Text unter den Feldern aktualisiert werden.

Wie kann ich diesen Code so ändern, dass die Viewmodel-Daten bei jedem Tastendruck aktualisiert werden?

alt text

<!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>

301voto

Sergei Golos Punkte 4323
<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>

Von der Dokumentation

Zusätzliche Parameter

  • valueUpdate

    Wenn Ihre Bindung auch einen Parameter namens valueUpdate enthält, wird dieser definiert, welches Browser-Ereignis KO verwenden soll, um Änderungen zu erkennen. Die folgenden String-Werte sind die gebräuchlichsten Auswahlmöglichkeiten:

    • "change" (Standard) - aktualisiert Ihr Ansichtsmodell, wenn der Benutzer den Fokus auf ein anderes Steuerelement verschiebt, oder im Fall von Elementen, sofort nach jeder Änderung

    • "keyup" - aktualisiert Ihr Ansichtsmodell, wenn der Benutzer eine Taste loslässt

    • "keypress" - aktualisiert Ihr Ansichtsmodell, wenn der Benutzer eine Taste eingegeben hat Taste eingegeben hat. Im Gegensatz zu "keyup" wird dieses Modell wiederholt aktualisiert, während der Benutzer eine Taste gedrückt hält down

    • "afterkeydown" - aktualisiert Ihr Ansichtsmodell, sobald der Benutzer beginnt, ein Zeichen zu tippen. Dies funktioniert durch Abfangen des Browser Keydown-Ereignis des Browsers abfängt und das Ereignis asynchron behandelt.

Von diesen Optionen ist "afterkeydown" die beste Wahl, wenn Sie wollen, dass Ihr Ansichtsmodell in Echtzeit aktualisiert werden soll.

87voto

Salvador Dali Punkte 197375

Unter Version 3.2 können Sie einfach verwenden Texteingabebindung. :

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

Sie erfüllt zwei wichtige Aufgaben:

  • sofortige Aktualisierungen vornehmen
  • behandelt Browserunterschiede für Ausschneiden, Ziehen, Autovervollständigen ...

Sie brauchen also keine zusätzlichen Module, benutzerdefinierte Steuerelemente und andere Dinge.

35voto

Jeff Mercado Punkte 120818

Wenn Sie möchten, dass das Programm Aktualisierungen vornimmt afterkeydown "standardmäßig", könnten Sie die valueUpdate Bindung im value Bindungs-Handler. Geben Sie einfach eine neue allBindingsAccessor für den zu verwendenden Handler, der Folgendes enthält 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
    };
} ());

Wenn es Ihnen unangenehm ist, die Funktion "Überschreiben" der value Bindung, können Sie der überschreibenden benutzerdefinierten Bindung einen anderen Namen geben und diesen Bindungshandler verwenden.

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

Demo

Eine solche Lösung wäre für Knockout Version 2.x geeignet. Das Knockout-Team hat eine vollständigere Anbindung für textähnliche Eingaben durch die textEingabe verbindlich in Knockout Version 3 und höher. Sie wurde entwickelt, um alle Texteingabemethoden für Texteingaben zu verarbeiten und textarea . Es kann sogar Aktualisierungen in Echtzeit vornehmen, was diesen Ansatz praktisch überflüssig macht.

20voto

RockResolve Punkte 1353

Die Antwort von Jeff Mercado ist fantastisch, aber leider mit Knockout 3 gebrochen.

Aber ich habe die Antwort gefunden, die von den Ko-Entwicklern vorgeschlagen wurde, als ich die Änderungen an Knockout 3 durcharbeitete. Siehe die unteren Kommentare unter https://github.com/knockout/knockout/pull/932 . Ihr 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/

Editar Ko 3.2.0 hat jetzt eine vollständigere Lösung mit der neuen "textInput"-Bindung. Siehe SalvidorDali's Antwort

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X