positive numeric value extend observable
by rniemeyer
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.1.0.js"></script>
<div data-bind='template: { name: "personTemplate", foreach: persons }'>
<hr/>
<div data-bind="text: ko.toJSON(viewModel)"></div>
<script id='personTemplate' type='text/html'>
<div>
<input type="text" name="firstname" data-bind="value: firstname" />
<input type="text" name="lastname" data-bind="value: lastname" />
<input type="text" name="age" data-bind="value: age.forcePositive()" />
</div>
</script>
CSS
input { width: 75px; }
JavaScript
ko.observable.fn.forcePositive = function() {
var underlyingObservable = this;
if (!this.forcePositiveInterceptor) {
this.forcePositiveInterceptor = ko.computed({
read: this,
write: function(newValue) {
var current = underlyingObservable(),
valueToWrite = isNaN(newValue) ? 0 : parseFloat(+newValue);
if (valueToWrite < 0) {
valueToWrite = 0;
}
//only write if it changed
if (valueToWrite !== current) {
underlyingObservable(valueToWrite);
} else {
//if the rounded value is the same as it was, but a different value was written, force a notification so the current field is updated to the rounded value
if (newValue !== current) {
underlyingObservable.valueHasMutated();
}
}
}
});
}
return this.forcePositiveInterceptor;
};
var viewModel = {
persons: ko.observableArray([{"firstname":"Kenneth","lastname":"None","age":ko.observable(37)},{"firstname":"Michael","lastname":"None","age":ko.observable(45)}]),
save: function() {
console.log('saving model with...');
console.log(ko.toJS(viewModel));
}
};
ko.applyBindings(viewModel);