Wouldn’t it be nice if we could restrict the value written to a Knockout observable? Some values might mess up your model completely while others just don’t make sense. How would one create a conditioned observable that rejects invalid values? It turns out that conditioning an observable is not so hard.

In this article I’m using TypeScript, but it isn’t difficult to port it to JavaScript. I’ll be sharing the code as a Gist (at the end). Note that the given solution might be too ridged as it flatly rejects all values that do not satisfy the condition.

A small example: Sudoku

Let’s think of a Sudoku-cell. The value of this cell is constricted by a number of possible values: 1-9. It is also limited by the numbers used in the adjacent vertical and horizontal rows (orange) and the box the cell is in (purple).

Not allowed due to row: 1, 4, 7, 8. Not allowed due to box: 2, 3, 6, 8, 9. Allowed: 5.

One could model this Sudoku-cell like a class with options and a value. Options can be removed from the cell and when a value is set, it should be checked if that value is still an option.

How would one restrict the value?

Enter the Conditioned Observable

Let’s extend Knockout with a¬†conditionedObservable<T> that takes an initial value and a condition lambda. First we’ll need to go through some TypeScript-trouble to get everything type-safe. Note: this overhead will not be compiled into JavaScript.

Inner workings

The basic idea comes from this blog. Building the Conditional Observable works as follows:

  • Create a¬†hidden observable that stores the value.
  • Return a¬†writable computed observable based on the¬†hidden observable.
  • When something is written to the computed observable, validate it before accepting it.

Implementation

Observe the implementation:

Looks pretty simple. Yet it is very effective.

Conditioning in action

Let’s add it to the example¬†Cell class. The observable is now conditioned to only¬†null or values that are in the¬†options array.

Notice how lambda expressions (ES6 arrow function) allow the code to use the this in a more intuitive way.

Summary

Knockout is a versatile MVVM-framework that allows you to build new features into it. With a few lines of code you can add constraints to your observables. Conditioning made easy. The JavaScript code for the Conditioned Observable is found here.