this might be easiest to describe with a fiddle http://jsfiddle.net/LkqTU/32190/
I have an observable called price which has an extender so that it rounds to two digits and does not allow non numeric.
I have a writable computed observable that puts a dollar sign in front of it.
however if the extender returns 0. the second time it happens $0 is not returned to the textbox (the computed observable) so if I type hello world in the textbox (computed observable) the price correctly reports 0 and the formatted price shows $0. however if I clear it out and type in hello world a second time. this time price is still $0 but the formatted price textbox is showing hello world (even though formatted price is reporting $0). must be missing a notification somewhere?
here is the code.
ko.extenders.numeric = function(target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko.pureComputed({
read: target, //always return the original observables value
write: function(newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({
notify: 'always'
});
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
function model() {
var self = this;
this.price = ko.observable('29.01').extend({
numeric: '2'
});
this.formattedPrice = ko.computed({
read: function() {
return '$' + this.price()
},
write: function(value) {
value = parseFloat(value.replace(/[^\.\d]/g, ""));
this.price(isNaN(value) ? 0 : value);
},
owner: this
});
}
var mymodel = new model();
$(document).ready(function() {
ko.applyBindings(mymodel);
});