knockout.js - tutorial - observablearray knockout example
Knockout.js: formato de entrada de tiempo y restricción de valor (1)
Cuando ato los datos numéricos en mi modelo de vista usando knockout, se muestra correctamente pero cambia el tipo de datos a cadena si el usuario cambia el valor de la etiqueta de entrada. El problema al enviar cadena es que el servidor espera un valor numérico sin conversión implícita disponible.
¿Alguna forma de decirle a knockout que mantenga el tipo de datos del valor de propiedad original?
Mi código de ejemplo que coincide con los nombres de modelo de vista a los nombres de etiqueta de entrada. Uso un knockout discreto para hacer las fijaciones, que funciona bien.
// Bind the first object returned to the first view model object
// FNS is the namespace, VM is the view model
FNS.VM.Items[0] = ko.mapping.fromJS(data.Items[0]);
// For each property found, find the matching input and bind it
$.each(FNS.VM.Items[0], function (indexInArray, valueOfElement) {
var attrName = indexInArray;
var attrValue;
if (typeof valueOfElement == "function")
attrValue = valueOfElement();
else
attrValue = valueOfElement;
var a = $(''input[name="'' + attrName + ''"][type="checkbox"]'');
if (a.length)
a.dataBind({ checked: ''VM.Items[0].'' + attrName });
var b = $(''input[name="'' + attrName + ''"][type="radio"]'');
if (b.length)
b.dataBind({ checked: ''VM.Items[0].'' + attrName });
var c = $(''input[name="'' + attrName + ''"][type="text"]'');
if (c.length)
c.dataBind({ value: ''VM.Items[0].'' + attrName });
});
ko.applyBindings(FNS);
Aquí hay un hilo con algunas técnicas diferentes para mantener el valor numérico: https://groups.google.com/d/topic/knockoutjs/SPrzcgddoY4/discussion
Una opción es llevar esta preocupación a su modelo de vista y crear un numericObservable
para usar en lugar de un observable normal. Puede verse así:
ko.numericObservable = function(initialValue) {
var _actual = ko.observable(initialValue);
var result = ko.dependentObservable({
read: function() {
return _actual();
},
write: function(newValue) {
var parsedValue = parseFloat(newValue);
_actual(isNaN(parsedValue) ? newValue : parsedValue);
}
});
return result;
};
Muestra: http://jsfiddle.net/rniemeyer/RJbdS/
Otra opción es manejar esto con un enlace personalizado. En lugar de usar el enlace de value
, puede definir un enlace de valor numericValue
y usarlo en su lugar. Podría verse así:
ko.bindingHandlers.numericValue = {
init : function(element, valueAccessor, allBindings, data, context) {
var interceptor = ko.computed({
read: function() {
return ko.unwrap(valueAccessor());
},
write: function(value) {
if (!isNaN(value)) {
valueAccessor()(parseFloat(value));
}
},
disposeWhenNodeIsRemoved: element
});
ko.applyBindingsToNode(element, { value: interceptor }, context);
}
};
Muestra: http://jsfiddle.net/rniemeyer/wtZ9X/