Cliff Chambers February 2016

Knockout JS Error: Cannot write a value to a ko.computed unless you specify a 'write' option

Having an issue that isn't necessarily game breaking. I have a simple table with sort, and 2 filters. One filter populated by array (active, inactive, show all) and one based on search criteria.

The code works. But when I have developer tools up I get the following 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.

My code is below, and I set up a JS Fiddle but I can't get it work, so I'm not sure it's helpful - Fiddle

var sgsoip = window.sgsoip || {};
sgsoip.FunctionalArea = function (FunctionalAreaID, FunctionalAreaName, FunctionalAreaActive) {
    'use strict';
    this.FunctionalAreaID = ko.observable(FunctionalAreaID);
    this.FunctionalAreaName = ko.observable(FunctionalAreaName);//.extend({ required: "Functional Area Name is required" });
    this.FunctionalAreaActive = ko.observable(FunctionalAreaActive);//.extend({ required: "Active is required" });
    //this.HasError = ko.pureComputed(function () {
    //    return this.FunctionalAreaActive.hasError() || this.FunctionalAreaName.hasError();
    //}, this);
};

var sgsoip = window.sgsoip || {};
sgsoip.FunctionalAreaViewModel = function (ko) {
    var self = this;
    self.functionalAreas = ko.observableArray([]);
    self.search = ko.observable('');

    
    self.headers = [
        { title: '', sortPropertyName: '', asc: true, active: false },
        { title: 'Functional Area Name', sortPropertyName: 'FunctionalAreaName', asc: true, active: true },
        { title: 'Active', sortPropertyName: 'FunctionalAreaActive', asc: true, active: false }
    ];
    self.filters = [
        { title: "Show All", f        

Answers


Tomalak February 2016

You bind your search input like this

<input name="searchString" data-bind="
    value: search, 
    valueUpdate: 'afterkeydown', 
    event: { 
        keyup: filteredItems
    }
"> 

which means knockout will call filteredItems every time the keyup event happens. filteredItems is defined as:

self.filteredItems = ko.computed(function () { /* ... */ })

i.e. a read-only computed. If you call that with any argument, knockout will complain that it can't write to a read-only computed. So don't do that.

<input name="searchString" data-bind="textInput: search"> 

It's unclear what this event binding was supposed to achieve anyway.

Also see: http://knockoutjs.com/documentation/textinput-binding.html


Barry Franklin February 2016

You could always just make a writable computed observable:

 this.fullName = ko.pureComputed({
    read: function () {
        return this.firstName() + " " + this.lastName();
    },
    write: function (value) {
        var lastSpacePos = value.lastIndexOf(" ");
        if (lastSpacePos > 0) { // Ignore values with no space character
            this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
            this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
        }
    },
    owner: this
});

From: http://knockoutjs.com/documentation/computed-writable.html

Post Status

Asked in February 2016
Viewed 2,353 times
Voted 10
Answered 2 times

Search




Leave an answer