style knockout data javascript knockout.js

javascript - data - ¿Cómo puedo hacer que Knockout JS se vincule con datos en la pulsación de tecla en lugar de en foco perdido?



ko js subscribe (4)

En la versión 3.2 , simplemente puede usar el enlace de entrada de texto. :

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

Hace dos cosas importantes:

  • hacer actualizaciones inmediatas
  • maneja las diferencias del navegador para cortar, arrastrar, autocompletar ...

Así que no hay necesidad de módulos adicionales, controles personalizados y otras cosas.

Este ejemplo de knockout js funciona de manera que cuando edita un campo y presiona TAB, se actualizan los datos del modelo de vista y, por lo tanto, el texto debajo de los campos.

¿Cómo puedo cambiar este código para que los datos del modelo de vista se actualicen con cada pulsación de tecla?

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


La respuesta de Jeff Mercado es fantástica, pero desafortunadamente se rompió con Knockout 3.

Pero encontré la respuesta sugerida por los desarrolladores de ko mientras trabajaba en los cambios de Knockout 3. Vea los comentarios de abajo en https://github.com/knockout/knockout/pull/932 . Su código:

//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 ahora tiene una solución más completa con el nuevo enlace "textInput". Ver la respuesta de SalvidorDali


Si desea que se realicen actualizaciones en afterkeydown "de forma predeterminada", puede inyectar el enlace valueUpdate en el controlador de enlace de value . Solo suministre un nuevo allBindingsAccessor para que el controlador lo use y que incluya 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 no se siente cómodo al "sobreescribir" el enlace de value , podría darle al enlace personalizado primordial un nombre diferente y usar ese controlador de enlace.

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

demo

Una solución como esta sería adecuada para Knockout versión 2.x. El equipo de Knockout ha desarrollado un enlace más completo para las entradas de texto a través del enlace de entrada de texto en la versión 3 de Knockout y posteriores. Fue diseñado para manejar todos los métodos de entrada de texto para entradas de texto y área de textarea . Incluso manejará la actualización en tiempo real, lo que efectivamente hace que este enfoque sea obsoleto.


<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

Parámetros adicionales

  • valueUpdate

    Si su enlace también incluye un parámetro llamado valueUpdate, esto define qué evento de navegador KO debe usar para detectar cambios. Los siguientes valores de cadena son las opciones más útiles:

    • "cambiar" (predeterminado): actualiza su modelo de vista cuando el usuario mueve el foco a un control diferente, o en el caso de los elementos, inmediatamente después de cualquier cambio

    • "keyup": actualiza su modelo de vista cuando el usuario suelta una tecla

    • "presionar tecla": actualiza su modelo de vista cuando el usuario ha escrito una clave. A diferencia de la tecla, esto se actualiza repetidamente mientras el usuario mantiene presionada una tecla

    • "afterkeydown": actualiza su modelo de vista tan pronto como el usuario comienza a escribir un carácter. Esto funciona capturando el evento de selección del navegador y manejando el evento de forma asíncrona.

De estas opciones, "afterkeydown" es la mejor opción si desea mantener su modelo de vista actualizado en tiempo real.