I have an observable that I bind to a input type="text"
HTML element. The observable holds floating point numbers. I want the value in the textbox to be displayed to 2 decimal places. So 1 would be 1.00, 1.2 would be 1.20 and so on. I created a custom binding that I think works for outputting the formatted value but doesn't capture the user input:
ko.bindingHandlers.numericValue = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
precision = ko.utils.unwrapObservable(allBindingsAccessor().precision) || ko.bindingHandlers.numericValue.defaultPrecision;
var formattedValue = '';
if (value) {
if (typeof value === "string") {
value = parseFloat(value);
}
formattedValue = value.toFixed(precision);
} else {
value = 0;
formattedValue = value.toFixed(precision);
}
$(element).val(formattedValue);
},
defaultPrecision: 1
};
Binding:
<input type="text" maxlength="6" class="bb width-100p" data-bind="numericValue: marketRate, precision: 2" />
Observable on model:
self.marketRate = ko.observable(formatNumber(dc.marketRate, 2)).extend({
required: { message: 'Required', onlyIf: function() { return self.isSelected(); }},
min: { params: 0, onlyIf: function () { return self.isSelected(); } },
max: { params: 999999.99, onlyIf: function() { return self.isSelected(); } },
pattern: { message: 'Maximum 2 decimal places', params: /^\d*(\.\d{1,2})?$/, onlyIf: function () { return self.isSelected(); } }
});
function formatNumber(value, places) {
value = ko.utils.unwrapObservable(value);
if (value) {
if (typeof value === "string") {
value = parseFloat(value);
}
return value.toFixed(places);
}
value = 0;
return value.toFixed(places);
}
Do I need something to update the observable with the value that the user has entered? This code never updates the observable. My guess is that I need to call into the Knockout value binding code.