Search code examples
javascriptdesign-patternsmoduledurandaltodomvc

Durandal TodoMVC - Cannot write a value to a ko.computed


I'm trying to build a version of the todo app using Durandal (including Knockout + RequireJS) from a TodoMVC template. I realize that a todo app doesn't really show off the features of Durandal, but I'm on the learning path and figured it would be a good first project.

Anyway, in the process I've stumbled upon an error that I'm unable to solve (see below).

Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.")

I've also attached an image that shows these in the console.

ko.computed errors

You can find the source code at https://github.com/robksawyer/durandal-todo. The todo viewmodel is located at https://github.com/robksawyer/durandal-todo/blob/master/viewmodels/todos.js.

Update: Most of the Knockout code is borrowed from the Knockout+Require TodoMVC project at https://github.com/tastejs/todomvc/tree/gh-pages/labs/dependency-examples/knockoutjs_require/

Thanks for your time.


Solution

  • I think you're misreading the console.

    For example, "allCompleted" is a property on your view model, which is declared as a dependent observable (i.e. a "computed"):

    // writeable computed observable to handle marking all complete/incomplete
    self.allCompleted = ko.computed({
        // -- trimmed --
    });
    

    What you're seeing in the console isn't the Cannot write a value error; it's the debug output for a computed property - i.e. its function definition. For reference, here's the function definition of a dependent observable straight from the knockout (2.2.1) source:

    function dependentObservable() {
        if (arguments.length > 0) {
            if (typeof writeFunction === "function") {
                // Writing a value
                writeFunction.apply(evaluatorFunctionTarget, arguments);
            } else {
                throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
            }
            return this; // Permits chained assignments
        } else {
            // Reading the value
            if (!_hasBeenEvaluated)
                evaluateImmediate();
            ko.dependencyDetection.registerDependency(dependentObservable);
            return _latestValue;
        }
    }
    

    What you're seeing in your console is the minified version of this code.

    If you want to see the value that's returned by the property you'd have to invoke it.