Get previous value of an observable in subscribe of same observable

knockout.jsKnockout 2.0Observable

knockout.js Problem Overview


Is it possible in knockout to get the current value of an observable within a subscription to that observable, before it receives the new value?

Example:

this.myObservable = ko.observable();
this.myObservable.subscribe(function(newValue){
    //I'd like to get the previous value of 'myObservable' here before it's set to newValue
});

knockout.js Solutions


Solution 1 - knockout.js

ko.subscribable.fn.subscribeChanged = function (callback) {
    var oldValue;
    this.subscribe(function (_oldValue) {
        oldValue = _oldValue;
    }, this, 'beforeChange');

    this.subscribe(function (newValue) {
        callback(newValue, oldValue);
    });
};

Use the above like this:

MyViewModel.MyObservableProperty.subscribeChanged(function (newValue, oldValue) {

});

Solution 2 - knockout.js

There is a way to do a subscription to the before value like this:

this.myObservable = ko.observable();
this.myObservable.subscribe(function(previousValue){
    //I'd like to get the previous value of 'myObservable' here before it's set to newValue
}, this, "beforeChange");

Solution 3 - knockout.js

Little change to Beagle90 answer. Always return the subscription itself to be able to access the dispose() for instance.

ko.subscribable.fn.subscribeChanged = function (callback) {
    var oldValue;
    this.subscribe(function (_oldValue) {
        oldValue = _oldValue;
    }, this, 'beforeChange');

    var subscription = this.subscribe(function (newValue) {
        callback(newValue, oldValue);
    });

    // always return subscription
    return subscription;
};

Solution 4 - knockout.js

The pull request to add this feature has some different code that winds up being better than relying on using the beforeChange event.

All credit for the solution to Michael Best

ko.subscribable.fn.subscribeChanged = function (callback) {
    var savedValue = this.peek();
    return this.subscribe(function (latestValue) {
        var oldValue = savedValue;
        savedValue = latestValue;
        callback(latestValue, oldValue);
    });
};

To quote Michael:

> I originally suggested using beforeChange to solve this problem but have since realized that it's not always reliable (for example, if you call valueHasMutated() on the observable).

Solution 5 - knockout.js

I have found that I can call peek() from a writable computed observable to get the before value.

Something like this (see http://jsfiddle.net/4MUWp):

var enclosedObservable = ko.observable();
this.myObservable = ko.computed({
    read: enclosedObservable,
    write: function (newValue) {
        var oldValue = enclosedObservable.peek();
        alert(oldValue);
        enclosedObservable(newValue);
    }
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKodeKreachorView Question on Stackoverflow
Solution 1 - knockout.jsJBeagleView Answer on Stackoverflow
Solution 2 - knockout.jsRP NiemeyerView Answer on Stackoverflow
Solution 3 - knockout.jsAndriesView Answer on Stackoverflow
Solution 4 - knockout.jsJames JohnsonView Answer on Stackoverflow
Solution 5 - knockout.jsrjmunroView Answer on Stackoverflow