2012-09-06 12 views
10

Sono nuovo su Knockout.js.Seleziona() Campo di immissione con Knockout.js

Qual è il modo migliore -select() un <input /> quando diventa visibile?

Vista:

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

ViewModel:

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/

Grazie!

risposta

18

È possibile creare una nuova rilegatura per gestire la selezione.

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

Aggiungi questa associazione al campo di inserimento.

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

Ecco un violino: http://jsfiddle.net/RnCUd/2/


In alternativa, è possibile creare un costume vincolante che avvolge il hasfocus rilegatura:

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(); 
    } 
}; 

Questo legame semplicemente delegati inizializzazione e aggiornamento per hasfocus e si occupa di selezionare l'elemento se l'osservabile è vero. Usalo invece di hasfocus.

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

Ecco un violino: http://jsfiddle.net/RnCUd/1/

+0

grazie per la risposta veloce :) sta utilizzando le associazioni personalizzate * troppo * a questo punto? Forse questo è il ** migliore **, ma avevo pensato che i binding personalizzati fossero avanzati ... c'è un modo "abbastanza buono" più semplice che non usi i binding personalizzati? O i binding personalizzati non sono un grosso problema e dovrei imparare a usarli presto e spesso? (Nota: non sono mai stato uno a creare selettori jQuery personalizzati) :) –

+2

@QuangVan Vorrei esortarvi a conoscere i binding personalizzati. Quando il problema attraversa la linea tra i tuoi dati e il DOM e non può essere risolto dai bind standard, i collegamenti personalizzati sono la scelta giusta. Direi che dovresti sentirti libero di "usarli presto e spesso" come hai detto tu. Sono uno strumento potente che non deve essere l'ultima risorsa. –

+0

okay, ho avuto la mentalità di essere "l'ultima risorsa" ... Grazie :) –

1

ho cercato di utilizzare John Earles personalizzato vincolante sopra (Grazie John!) Insieme a un campo di testo che ha utilizzato anche una valueUpdate: 'afterkeydown' vincolante ed ha scoperto che non ha funzionato come previsto. (Immagino che questo sia dovuto al fatto che tutti i binding si attivano di nuovo quando uno dei binding deve sparare, e valueUpdate molto probabilmente causa il binding del valore dopo che ogni carattere è stato scritto).

Dopo un paio di tentativi ho fatto una semifissa per questo problema che sembra funzionare bene per me. L'idea di base è che prima di sparare il binding di hasfocus controlliamo se l'elemento in questione ha già il focus e selezioniamo il testo solo quando l'elemento non ha effettivamente messo a fuoco prima che il binding di hafocus abbia sparato.

Ho usato jquery per verificare la messa a fuoco, ma probabilmente lo si potrebbe fare anche in un altro modo.

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(); 
     } 
    } 
}; 

Edit: Ho notato che questo tipo di legame potrebbe non funzionare esattamente come si desidera quando viene utilizzato su un dispositivo iOS. Non c'è niente di sbagliato nell'associazione in quanto tale, ma la messa a fuoco automatica e la logica di selezione fanno in modo che la tastiera dei dispositivi venga visualizzata non appena l'associazione viene eseguita che può o non può essere esattamente ciò che si desidera che si verifichi su tale dispositivo. Per fare un confronto, sui dispositivi Android che uso per testare non ottengo automaticamente la tastiera non appena questa associazione viene eseguita. Per il mio bene ho finito per creare un altro legame per non fare nulla sui dispositivi iOS nel modo seguente.

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:

Se si utilizza questo e vuole soddisfare tablet/smartphone quindi assicuratevi di verificare che questa è la logica di interazione che in realtà aspetta.

Problemi correlati