SteveSanderson / knockout.mapping

Object mapping plugin for KnockoutJS
Other
546 stars 767 forks source link

"wrap" function makes computed writable #91

Closed lisandropuzzolo closed 12 years ago

lisandropuzzolo commented 12 years ago

On function withProxyDependentObservable, the wrap function makes all computed writable.

Solution:

function withProxyDependentObservable(dependentObservables, callback) { var localDO = ko.dependentObservable; ko.dependentObservable = function (read, owner, options) { options = options || {};

        if (read && typeof read == "object") { // mirrors condition in knockout implementation of DO's
            options = read;
        }

        var realDeferEvaluation = options.deferEvaluation;

        var isRemoved = false;

        // We wrap the original dependent observable so that we can remove it from the 'dependentObservables' list we need to evaluate after mapping has
        // completed if the user already evaluated the DO themselves in the meantime.
        var wrap = function (DO) {
            var wrapped = realKoDependentObservable({
                read: function () {
                    if (!isRemoved) {
                        ko.utils.arrayRemoveItem(dependentObservables, DO);
                        isRemoved = true;
                    }
                    return DO.apply(DO, arguments);
                },
                write: DO.hasWriteFunction && function (val) { //  ***** HERE IS THE FIX *****
                    return DO(val);
                },
                deferEvaluation: true
            });
            if(DEBUG) wrapped._wrapper = true;
            return wrapped;
        };

        options.deferEvaluation = true; // will either set for just options, or both read/options.
        var realDependentObservable = new realKoDependentObservable(read, owner, options);

        if (!realDeferEvaluation) {
            realDependentObservable = wrap(realDependentObservable);
            dependentObservables.push(realDependentObservable);
        }

        return realDependentObservable;
    }
    ko.dependentObservable.fn = realKoDependentObservable.fn;
    ko.computed = ko.dependentObservable;
    var result = callback();
    ko.dependentObservable = localDO;
    ko.computed = ko.dependentObservable;
    return result;
}
sagacity commented 12 years ago

Thanks for letting me know. This will be fixed in the next release.

wjbryant commented 12 years ago

It looks like hasWriteFunction is considered part of the private API since it's mangled/obfuscated in the minified build. Replacing DO.hasWriteFunction with ko.isWriteableObservable(DO) should work in both the debug and minified builds.

sagacity commented 12 years ago

Good catch, I'll fix that.