Will
Cannings

Key Value Coding is a simple extension to the observer pattern. Rather than blindly observing ‘change’ in an object (where any property could have changed), observers register to be informed about changes to specific ‘keys’ or properties of an object. This allows you to bind different elements in your web app and have them all magically stay in sync. An object representing a record of some sort (say an address contact) can inform all the user interface elements observing it of a change to any of its values. You could have a text field that sets the email property of the record; all elements observing the property (such as a tag) are automatically informed whenever the property changes, and have a chance to update themselves. The pattern decouples model and view, allowing you to add, edit and remove views without ever having to change your model.

Implementing the pattern is easy in JavaScript because all objects act like hashtables. To glue the whole process together we need a few things:

  • An interface for communicating with observers
  • An interface for registering observers
  • A way to intercept changes to values

An interface for communicating with observers

Observers are informed whenever a property they are watching changes. Because an observer may be watching more than one property of an object (and even more than one object), we need to supply the key (property name) along with the value, as well as the object being updated. It’s often also useful to know the previous value of the property, so observers can test to see if a value was actually updated, or merely re-assigned to.

For example, say we have an object representing a square element on a page that can be resized and dragged. The object could have four properties: top, left, width, height. The code that implements the dragging and resizing assigns values to all four of these properties live as the square’s position and dimensions are being changed. Something as simple as a P element could be observing the top property and change its text to match the value of the property whenever it changes. But during a resize, the top and left values won’t change; only the width andheight will be updated. Because the resize operation assigns to all four properties, we’ll trigger a notification on all four, even though the values for top and left haven’t actually changed.

To be able to support this behaviour, we can use a callback defined like this:

keyWillUpdate(object, key, previousValue, newValue)

The P element could implement this function like this:

document.getElementById("our_p_tag").keyWillUpdate = function(object, key, previousValue, newValue) {
  if(previousValue == newValue) return;
  this.innerHTML = newValue;
}

This will ignore updates where the value has been assigned to but not changed.

An interface for registering observers

When an observer registers with a KVC object we need to know which property it is observing, and to keep track of all the observers for each property. A simple register function on an object could look like:

function registerObserver(observer, key) {
  if(this.observers == null)
    this.observers = {};
  if(this.observers[key] == null)
    this.observers[key] = [observer];
  else
    this.observers[key].push(observer);
}

Here we use a hashtable (observers) to store the list of observers for each property. The key of the observers table is the property being observed, and the value is an array of objects observing the property. When it comes time to notify observers of an assignment to a property, we can easily iterate through the array.

A way to intercept changes to values

Unfortunately there’s no sneaky way to do this cleanly in Javascript. Other languages allow you to catch method calls that don’t match a defined method (e.g method_missing in Ruby), but we can’t do that in Javascript. Instead we need to define a set function that must be called when assigning to a value for our KVC interface to work correctly. Because no KVC operations are performed when retrieving a value, technically we don’t need a corresponding get function, but for completeness and consistency it’s good to have. We could implement these functions like this:

function get(key) {
  return this[key];
}

function set(key, value) {
  if(this.observers != null && this.observers[key] != null) {
    currentValue = this[key];
    for(var i = 0; i < this.observers[key].length; i++)
      this.observers[key][i].keyWillUpdate(this, key, currentValue, value);
  }
  this[key] = value;
}

A call to a KVC object like square.set(‘top’, 20) will now inform all observers of top property of the new assignment to that property.

Why is this useful?

For a simple web app KVC may seem like overkill, however the benefits are immense for medium to large apps. I recently wrote an app that had a draggable calendar interface – click to create events on a day, drag events around to indicate days and time, and resize events to indicate length of time. There were two bits to the UI for each event: the draggable box on the calendar, and a set of text fields where you could manually type in times and other options for the event.

Keeping the two in sync could have been difficult, and if a third UI element was added to track the event it would have been even more unmanageable. Using KVC, all UI elements observed the start and end times for each event. When a text field updated the start time of an event, the draggable box observing the event was informed of the change and updated it’s display accordingly. Vice versa, when the event box was dragged within the calendar, it updated the times in the event model, and the text fields showing the start and end times were immediately updated to reflect the new times.

The model didn’t need to ‘know’ about either of the UI views, and neither view had to know about each other. It decoupled all elements from each other and made synchronisation simple. Adding a third UI element to track the event would have been easy, and again, would ‘magically’ stay in sync with the rest of the elements.

Sample code

sample page showing a sample implementation of a KVC object constructor, a checkbox setting a property in a KVC object, and a P tag observing the property.