Dieses Beispiel für knockout js funktioniert, wenn Sie ein Feld bearbeiten und die Tabulatortaste drücken, werden die Ansichtsmodelldaten und damit der Text unter den Feldern aktualisiert.
Wie kann ich diesen Code ändern, damit die Ansichtsmodelldaten bei jedem Tastendruck aktualisiert werden?
<!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>
<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>
Aus der Dokumentation
Zusätzliche Parameter
valueUpdate
Wenn Ihre Bindung auch einen Parameter mit dem Namen valueUpdate enthält, wird hiermit festgelegt, welches Browserereignis KO zum Erkennen von Änderungen verwenden soll. Die folgenden Zeichenfolgenwerte sind die am häufigsten verwendeten Optionen:
"change" (Standardeinstellung) - Aktualisiert Ihr Ansichtsmodell, wenn der Benutzer den Fokus auf ein anderes Steuerelement oder bei Elementen unmittelbar nach einer Änderung verschiebt
"keyup" - Aktualisiert Ihr Ansichtsmodell, wenn der Benutzer einen Schlüssel freigibt
"Tastendruck" - Aktualisiert Ihr Ansichtsmodell, wenn der Benutzer eine Taste eingegeben hat. Im Gegensatz zu keyup wird dies wiederholt aktualisiert, während der Benutzer eine Taste gedrückt hält
- "afterkeydown" - aktualisiert Ihr Ansichtsmodell, sobald der Benutzer ein Zeichen eingibt. Dies funktioniert, indem das Keydown-Ereignis des Browsers abgefangen und das Ereignis asynchron behandelt wird.
Von diesen Optionen ist "Afterkeydown" die beste Wahl, wenn Sie Ihr Ansichtsmodell in Echtzeit aktualisieren möchten.
In Version 3.2 können Sie einfach Texteingabebindung verwenden. :
<input data-bind="textInput: userName" />
Es macht zwei wichtige Dinge:
Es sind also keine zusätzlichen Module, benutzerdefinierten Steuerelemente und andere Dinge erforderlich.
Wenn Sie möchten, dass Aktualisierungen für afterkeydown
"standardmäßig" durchgeführt werden, können Sie die Bindung valueUpdate
in den Bindungshandler value
einfügen. Geben Sie einfach ein neues allBindingsAccessor
für den Handler an, das afterkeydown
enthält.
(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 Sie die Bindung value
nicht "überschreiben" möchten, können Sie der überschreibenden benutzerdefinierten Bindung einen anderen Namen geben und diesen Bindungshandler verwenden.
ko.bindingHandlers.realtimeValue = { 'init':..., 'update':... };
Eine solche Lösung wäre für die Knockout-Version 2.x geeignet. Das Knockout-Team hat eine vollständigere Bindung für textähnliche Eingaben durch die Bindung textInput in Knockout Version 3 und höher erstellt. Es wurde entwickelt, um alle Texteingabemethoden für Texteingaben und textarea
zu verarbeiten. Es kann sogar in Echtzeit aktualisiert werden, was diesen Ansatz praktisch überflüssig macht.
Jeff Mercados Antwort ist fantastisch, aber leider mit Knockout 3 gebrochen.
Aber ich habe die von den Ko-Entwicklern vorgeschlagene Antwort gefunden, als ich Knockout 3-Änderungen durchgearbeitet habe. 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/
Edit Ko 3.2.0 hat jetzt eine vollständigere Lösung mit der neuen Bindung "textInput". Siehe SalvidorDalis Antwort