Knockout Protected Observable

Knockout Protected Observable

by cjgaudin

HTML

<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-latest.debug.js"></script>
<div id="example">

    
</div>

JavaScript

//wrapper to an observable that requires accept/cancel
//http://www.knockmeout.net/2011/03/guard-your-model-accept-or-cancel-edits.html
ko.protectedObservable = function (initialValue) {
    //private variables
    var _actualValue, _tempValue;
    var unwrap = ko.utils.unwrapObservable;

    if (!ko.isObservable(initialValue)) {
        _actualValue = ko.observable(initialValue);
        _tempValue = initialValue;
    }
    else {
        _actualValue = initialValue;
        _tempValue = unwrap(initialValue);
    }

    //dependentObservable that we will return
    var result = ko.computed({
        //always return the actual value
        read: function () {
            return _actualValue();
        },
        //stored in a temporary spot until commit
        write: function (newValue) {
            _tempValue = newValue;
        }
    });

    //if different, commit temp value
    result.commit = function () {
        if (_tempValue !== _actualValue()) {
            _actualValue(_tempValue);
        }
    };

    //force subscribers to take original
    result.reset = function () {
        _actualValue.valueHasMutated();
        _tempValue = unwrap(_actualValue);   //reset temp value 
    };

    return result;
};

ko.toProtectedObservableItem = function (item) {
    var unwrap = ko.utils.unwrapObservable;
    var result = {};

    for (var param in item) {
        if (item.hasOwnProperty(param)) {
            if (item[param] instanceof Array) {
                result[param] = ko.observableArray(item[param]);
            }
            else {
                result[param] = ko.isObservable(result[param]) ? ko.protectedObservable(unwrap(item[param])) : ko.protectedObservable(item[param]);             
            }
        }
    }

    result.commit = function () {
        for (var prop in result) {
            if (result.hasOwnProperty(prop) && result[prop].commit) {
                result[prop].commit();
            }
        }
    };
    return...