As of now, Knockout allows you to subscribe to value change events on an observable as explained here. By default you can subscribe to change
and beforeChange
callbacks separately, but not through a common callback.
There is some discussion around a subscribeChanged
handler that notifies a callback function before the observable changes with its new and old values.1
From the same Github thread, I have used one of the implementations of subscribeChanged
extender. Using that, you can validate the value of the observable everytime it changes, and reset it to its original value if it does not meet the criteria.
In the snippet below, I am comparing the new value of the observable with the defined maximum value, and resetting the observable to its old value if the new value is greater than 100.
ko.subscribable.fn.subscribeChanged = function (callback) {
var savedValue = this.peek();
return this.subscribe(function (latestValue) {
var oldValue = savedValue;
savedValue = latestValue;
callback(latestValue, oldValue);
});
};
var model = function () {
var self= this;
self.number = ko.observable(0);
self.maxNumber = 100;
self.number.subscribeChanged(function(newValue, oldValue) {
if(newValue > self.maxNumber || // New value must not be larger than 100
(newValue != "" && parseFloat(newValue) != newValue)) { // New value must be a valid number
console.log('Rejecting value change.');
self.number(oldValue);
} else {
console.log("Old: " + oldValue + ", New: " + newValue);
}
});
}
ko.applyBindings(new model());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input data-bind="textInput: number" />
1: There is a slightly different implementation of a similar extender here:
https://stackoverflow.com/a/18184016/5894241