knockout error message

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.

by Cliff Chambers

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-1.12.0.js"></script>
<div class="container">
<div class="row">
  <div class="col-sm-2 col-md-1">
    <label for="searchString">Search:</label> 
  </div>
  <div class="col-sm-3">
    <input name="searchString" class="form-control" id="searchString" type="text" value="" data-bind="value: search, valueUpdate: 'afterkeydown', event: { keyup: filteredItems } "> 
  </div>
  <div class="col-sm-2 col-md-1">
    <label for="Filter:">Filter:</label>
  </div>
  <div class="col-sm-3">
    <div class="btn-group" data-bind="foreach: filters">
      <button class="btn btn-default" data-bind="click:  setActiveFilter, text: title">Show All</button>

      <button class="btn btn-default" data-bind="click:  setActiveFilter, text: title">Active</button>

      <button class="btn btn-default" data-bind="click:  setActiveFilter, text: title">Inactive</button>
    </div>
  </div>
</div>
    
<div class="row extraTopMargin">
  <div class="col-sm-12">
    <table class="table table-striped" id="gridoutput">
      <thead>
        <tr data-bind="foreach: headers">
          <th><a href="#" data-bind="click: sort, text: title"></a></th>
        </tr>
      </thead>
      <tbody data-bind="foreach: filteredItems">
        <tr>
          <td><a href="javascript:void(0);" data-bind="click: removeFunctionalArea" title="Delete"><i class="glyphicon glyphicon-trash"></i></a></td>
          <td data-bind="text: FunctionalAreaName"></td>
          <td data-bind="text: FunctionalAreaActive"></td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

</div>

CSS

.extraTopMargin { margin-top: 20px; }

JavaScript

//$(document).ready(function () {

  ko.applyBindings(sgsoip.FunctionalAreaViewModel);
  alert('test');
//});

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", filter: null },
        { title: "Active", filter: function (item) { return item.FunctionalAreaActive() === true; } },
        { title: "Inactive", filter: function (item) { return item.FunctionalAreaActive() === false; } }
    ];

    self.activeFilter = ko.observable(self.filters[0].filter);
    self.activeSort = ko.observable(function () { return 1; }); //set the default sort

    self.setActiveFilter = function (model, event) {
        self.activeFilter(model.filter);
    }
    
    self.sort = function (header, event) {
        //if this header was just clicked a second time
        if (header.active) {
            header.asc = !header.asc; //toggle the direction of the sort
        }
        //make sure all other headers are set to inactive
        ko.utils.arrayForEach(self.headers, function (item) { item.active = false; });
        //the header that was just clicked is now active
        header.active = true;//our now-active header

        var prop = header.sortPropertyName;
        var ascSort = function (a, b) { return a[prop]() < b[prop]() ? -1 : a[prop]() > b[prop]() ? 1 : a[prop]() == b[prop]() ? 0 : 0; };
        var descSort = function (a, b) { return a[prop]() > b[prop]() ? -1 : a[prop]() < b[prop]() ? 1 : a[prop]() == b[prop]() ? 0 : 0; };
        var sortFunc = header.asc ? ascSort : descSort;

...