2012-09-06 26 views
10

Soy nuevo en Knockout.js.Seleccionar() Campo de entrada con Knockout.js

Cuál es la manera mejor -select() un <input /> cuando se hace visible?

Vista:

<p> 
    Name: 
    <b data-bind="visible: !editing(), text: name, click: edit">&nbsp;</b> 
    <input data-bind="visible: editing, value: name, hasfocus: editing" /> 
</p> 

modelo de vista:

function PersonViewModel(name) { 
    // Data 
    this.name = ko.observable(name); 
    this.editing = ko.observable(false); 

    // Behaviors 
    this.edit = function() { this.editing(true) } 
} 

ko.applyBindings(new PersonViewModel("Bert Bertington")); 

http://knockoutjs.com/documentation/hasfocus-binding.html

http://jsfiddle.net/RnCUd/

Gracias!

Respuesta

18

Puede crear un nuevo enlace para manejar la selección.

ko.bindingHandlers.selected = { 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var selected = ko.utils.unwrapObservable(valueAccessor()); 
     if (selected) element.select(); 
    } 
}; 

Agregue este enlace a su campo de entrada.

<input data-bind="visible: editing, value: name, hasfocus: editing, selected: editing" /> 

Aquí es un violín: http://jsfiddle.net/RnCUd/2/


Como alternativa, puede crear una unión costumbre que envuelve el hasfocus vinculante:

ko.bindingHandlers.hasSelectedFocus = { 
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     ko.bindingHandlers['hasfocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
    },   
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     ko.bindingHandlers['hasfocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);   

     var selected = ko.utils.unwrapObservable(valueAccessor()); 
     if (selected) element.select(); 
    } 
}; 

Esta unión simplemente delegados de inicialización y actualización de hasfocus y se encarga de seleccionar el elemento si lo observable es verdadero. Úselo en lugar de hasfocus.

<input data-bind="visible: editing, value: name, hasSelectedFocus: editing" /> 

Aquí es un violín: http://jsfiddle.net/RnCUd/1/

+0

gracias por la respuesta rápida :) está utilizando enlaces personalizados * demasiado * en este momento? Tal vez ese sea el ** mejor **, pero pensé que los enlaces personalizados eran avanzados ... ¿hay una forma "lo suficientemente buena" que no utilice enlaces personalizados? ¿O las encuadernaciones personalizadas no son un gran problema y debería aprender a usarlas pronto y a menudo? (Nota: nunca fui uno para hacer selectores jQuery personalizados) :) –

+2

@QuangVan Le recomiendo encarecidamente que conozca los enlaces personalizados. Cuando el problema cruza la línea entre sus datos y el DOM y no puede ser resuelto por los enlaces estándar, entonces los enlaces personalizados son la opción correcta. Yo diría que debes sentirte libre de "usarlos temprano y a menudo" como dijiste. Son una herramienta poderosa que no necesita ser el último recurso. –

+0

bien, sí, tenía la mentalidad de que era el "último recurso" ... Gracias :) –

1

he tratado de usar a Juan Earles enlace personalizado anterior (Gracias Juan!) Junto con un campo de texto que también se utiliza un valueUpdate: 'afterkeydown' vinculante y descubrió que eso realmente no funcionó como se esperaba (Supongo que esto se debe a que todas las vinculaciones se activan de nuevo cuando una de las vinculaciones debe activarse, y es muy probable que valueUpdate haga que el valor vinculante se active después de que se haya escrito cada carácter).

Después de un par de intentos hice un semi-arreglo para este problema que parece estar funcionando bien para mí. La idea básica es que antes de desencadenar el encuadernado de hasfocus verificamos si el elemento en cuestión ya tiene foco y solo seleccionamos el texto cuando el elemento no tenía foco realmente antes de que se haya disparado el encuadernado hasfocus.

He usado jquery para comprobar el enfoque, pero probablemente también podría hacerlo de alguna otra forma.

ko.bindingHandlers.hasSelectedFocus = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     ko.bindingHandlers['hasfocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
    }, 
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var focusBefore = $(element).is(':focus'); 
     ko.bindingHandlers['hasfocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 

     var selected = ko.utils.unwrapObservable(valueAccessor()); 
     if (selected && !focusBefore) { 
      element.select(); 
     } 
    } 
}; 

Editar: Me he dado cuenta de que este tipo de unión podría no funcionar exactamente como se desea cuando se utiliza en un dispositivo iOS. No hay nada de malo con el enlace como tal, pero el enfoque automático y la lógica de selección hacen que el teclado del dispositivo aparezca tan pronto como se ejecuta el enlace, que puede o no ser exactamente lo que desea que suceda en dicho dispositivo. Para comparar, en los dispositivos con Android que uso para probar, no obtengo el teclado automáticamente tan pronto como se ejecuta este enlace. Por mi bien, terminé creando otro enlace para no hacer nada en los dispositivos iOS de la siguiente manera.

ko.bindingHandlers.hasNonIosSelectedFocus = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     if (navigator.userAgent.match(/iPad/i) == null && navigator.platform.indexOf("iPhone") == -1 && navigator.platform.indexOf("iPod") == -1) { 
      ko.bindingHandlers['hasSelectedFocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
     } 
    }, 
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     if (navigator.userAgent.match(/iPad/i) == null && navigator.platform.indexOf("iPhone") == -1 && navigator.platform.indexOf("iPod") == -1) { 
      ko.bindingHandlers['hasSelectedFocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
     } 
    } 
}; 

tl; dr:

Si utiliza esto y quiere atender a las tabletas/teléfonos inteligentes a continuación, asegúrese de probar que esta es la lógica de interacción que en realidad se espera.

Cuestiones relacionadas