This seems to be a common approach to sanitizing/validating/formatting data with knockout when binding to an input field, it creates a reusable custom binding that uses a co
The issue comes from the update
portion of your custom binding. This part will update the field based on the original model value. So, the event handler attached in the init
will send the new value through your writeable computed, but the updating of the field actually happens in the update
.
One option is to apply the value binding from your init
function and skip the update
function like:
ko.bindingHandlers.amountValue = {
init: function (element, valueAccessor, allBindingsAccessor) {
var underlyingObservable = valueAccessor();
var interceptor = ko.computed({
read: function () {
// this function does get called, but it's return value is not used as the value of the textbox.
// the raw value from the underlyingObservable, or the actual value the user entered is used instead, no
// dollar sign added. It seems like this read function is completely useless, and isn't used at all
return "$" + underlyingObservable();
},
write: function (newValue) {
var current = underlyingObservable(),
valueToWrite = Math.round(parseFloat(newValue.replace("$", "")) * 100) / 100;
if (valueToWrite !== current) {
// for some reason, if a user enters 20.00000 for example, the value written to the observable
// is 20, but the original value they entered (20.00000) is still shown in the text box.
underlyingObservable(valueToWrite);
} else {
if (newValue !== current.toString())
underlyingObservable.valueHasMutated();
}
}
});
ko.applyBindingsToNode(element, { value: interceptor });
}
};
Updated fiddle: http://jsfiddle.net/rniemeyer/Sr8Ev/