Binding true / false ai pulsanti di opzione in Knockout JS

Nel mio modello di vista ho un valore IsMale che ha il valore true o false.

Nella mia interfaccia utente desidero associarlo ai seguenti pulsanti di opzione:

  

Il problema che penso sia checked aspetta una stringa “true” / “false”. Quindi la mia domanda è, come posso ottenere questa associazione a 2 vie con questa UI e modello?

Un’opzione è usare un osservabile calcolato scrivibile .

In questo caso, penso che una buona opzione sia rendere l’osservabile IsMale scrivibile un “sotto-osservabile” del tuo osservabile IsMale . Il tuo modello di visualizzazione sarà simile a:

 var ViewModel = function() { this.IsMale = ko.observable(true); this.IsMale.ForEditing = ko.computed({ read: function() { return this.IsMale().toString(); }, write: function(newValue) { this.IsMale(newValue === "true"); }, owner: this }); }; 

Lo legeresti nella tua interfaccia utente come:

   

Esempio: http://jsfiddle.net/rniemeyer/Pjdse/

So che questo è un thread vecchio, ma stavo avendo lo stesso problema e ho scoperto una soluzione molto migliore che probabilmente è stata aggiunta ad eliminazione diretta dopo che questa domanda è stata ufficialmente risolta, quindi lo lascerò solo per le persone con lo stesso problema.

Attualmente non sono necessari estensori, gestori di binding personalizzati o calcoli. Fornisci solo un’opzione “checkedValue”, userà quella invece dell’attributo ‘value’ in html e con questa potrai passare qualsiasi valore javascript.

   

O:

    

Questo funziona per me:

http://jsfiddle.net/zrBuL/291/

   
 ko.bindingHandlers['radiobuttonyesno'] = { 'init': function (element, valueAccessor, allBindingsAccessor) { var stateHandler = function (property, allBindingsAccessor, key, value, checkIfDifferent) { if (!property || !ko.isObservable(property)) { var propWriters = allBindingsAccessor()['_ko_property_writers']; if (propWriters && propWriters[key]) propWriters[key](value); } else if (ko.isWriteableObservable(property) && (!checkIfDifferent || property.peek() !== value)) { property(value); } }; var updateHandler = function () { var valueToWrite; if ((element.type == "radio") && (element.checked)) { valueToWrite = element.value; } else { return; // "radiobuttonyesno" binding only responds to selected radio buttons } valueToWrite = (valueToWrite === "True") ? true : false; var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue); //can be true of false stateHandler(modelValue, allBindingsAccessor, 'checked', valueToWrite, true); }; ko.utils.registerEventHandler(element, "click", updateHandler); // IE 6 won't allow radio buttons to be selected unless they have a name if ((element.type == "radio") && !element.name) ko.bindingHandlers['uniqueName']['init'](element, function () { return true }); }, 'update': function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); value = value ? "True" : "False"; if (element.type == "radio") { element.checked = (element.value == value); } } }; 

Usa questo raccoglitore invece di creare stupidi osservabili calcolati di ko.

Esempio:

   

Una volta capito che la corrispondenza iniziale per il pulsante di opzione vuole corrispondere solo a una stringa e vuole impostare il valore su una stringa, si tratta semplicemente di convertire il valore iniziale in stringa. Ho dovuto combattere questo con i valori di Int.

Dopo aver impostato le tue osservabili, converti il ​​valore in stringa e KO farà la sua magia da lì. Se stai mappando con linee individuali, fai la conversione in quelle linee.

Nel codice di esempio, sto usando Json per mappare l’intero Modello in un singolo comando. Quindi lasciando che Razor inserisca il valore tra le virgolette per la conversione.

 script type="text/javascript"> KoSetup.ViewModel = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model))); KoSetup.ViewModel.ManifestEntered("@Model.ManifestEntered"); //Bool KoSetup.ViewModel.OrderStatusID("@Model.OrderStatusID"); //Int  

Io uso un “Dump tutto sullo schermo” nella parte inferiore della mia pagina web durante lo sviluppo.

 

Debug


Ecco i valori dei dati, Prima

 "OrderStatusID": 6, "ManifestEntered": true, 

e, dopo

 "OrderStatusID": "6", "ManifestEntered": "True", 

Nel mio progetto, non avevo bisogno di convertire Bool, perché sono in grado di utilizzare una casella di controllo che non ha la stessa frustrazione.

Perché non semplicemente vero e falso invece di 1 e 0?

    

Puoi anche usare un extender in modo che sia facile riutilizzarli per ulteriori osservabili:

 ko.extenders.boolForEditing = function (target, allowNull) { var result = ko.computed({ read: function () { var current = target(); var newValue = null; if (current === undefined || current === null || current === '') { if (!allowNull) { newValue = 'false'; } } else { newValue = current ? 'true' : 'false'; } return newValue; }, write: function (newValue) { var current = target(); var valueToWrite = null; if (newValue === undefined || newValue === null || newValue === '') { if (!allowNull) { valueToWrite = false; } } else { valueToWrite = newValue === 'true'; } // only write if it changed if (valueToWrite !== current) { target(valueToWrite); } else { if (newValue !== current) { target.notifySubscribers(valueToWrite); } } } }).extend({ notify: 'always' }); result(target()); return result; }; 

Quindi usalo in questo modo:

 this.IsMale.forEditing = this.IsMale.extend({boolForEditing: true}); 

Il parametro fornito su boolForEditing indica se il valore può essere nullo.

Vedi http://jsfiddle.net/G8qs9/1/

Dopo aver fatto molte ricerche per versioni precedenti di knockout precedenti alla 3.0, ci sono probabilmente due migliori opzioni

Crea un extender ad eliminazione diretta come

 ko.extenders["booleanValue"] = function (target) { target.formattedValue = ko.computed({ read: function () { if (target() === true) return "True"; else if (target() === false) return "False"; }, write: function (newValue) { if (newValue) { if (newValue === "False") target(false); else if (newValue === "True") target(true); } } }); target.formattedValue(target()); return target; }; 

Per usare l’extender sul tuo modello, dovresti fare qualcosa di simile al seguente:

 function Order() { this.wantsFries= ko.observable(false).extend({ booleanValue: null }); } Do you want fries with that?   

fonte: http://www.timlabonne.com/2013/02/building-a-knockout-js-extender-for-boolean-values/