Dojo 1.5 introduces a new paradigm for consistent interaction with stateful objects like widgets. Stateful objects now follow a pattern of using get() and set() methods for accessing and setting named properties. Following this paradigm, to get a named property from a widget, we now use:

widget.get("checked");

And to set a named property we do:

widget.set("checked", true);

This essentially supersedes the widget system’s attr() method, providing more readable function names that don’t require branching on variable argument length, and are more easily overridden. The attr() will remain in Dojo 1.5, but now delegates to get() and set(). The use of get() and set() is recommended over attr() now.

Introducing dojo.Stateful

Dojo also introduces a new constructor for creating stateful objects with the dojo.Stateful module. This module provides simple default get() and set() implementations as well as the third complementary method, the watch(). The watch() design is based on the Mozilla’s watch function, and provides an easy mechanism for monitoring state changes. Using dojo.Stateful, we can now create objects that can be mutated, read, as well as monitored:

var obj = new dojo.Stateful({
  price: 9.99
});

First, we created a new Stateful object with a property price set to 9.99. Now, we can monitor that object for changes:

obj.watch("price", function(){
  console.log("price changed to " + this.get("price"));
});

Later if the property is changed:

obj.set("price", 6.99);

This will fire the watch callback function that prints out the new price.

The watch function returns an object that can later be used to discontinue a watch by calling the unwatch() method. For example:

watchHandle = obj.watch("price", callback);
...
// no longer want to watch:
watchHandle.unwatch();

Possibilities and future directions using Stateful

While widgets in Dojo 1.5 will only provide get() and set() methods (not watch()), we are hoping to have dijit._Widget subclass dojo.Stateful in 1.6 providing a convenient and consistent approach to monitoring widget property changes as well as other objects. We will then be able to use the watch method on any widget.

We are also considering a new Dojo Data design where data items would also follow this interface, allowing even broader consistency in a uniform interface for accessing and monitoring stateful objects, whether they are items from a data store, widgets, or other user objects that extend dojo.Stateful.

One of the key motivations for this design is that it would ultimately enable building functionally reactive “live” templating engines or data-bindings on top of Dojo. The concepts of functional reactive design (or data-bindings) have been demonstrated in other projects like Flex, Flapjax, and Fin. Eventually we will be able to write templates like:

${obj.get("foo")}

And the templating engine could determine that it needs to call the watch method to monitor object obj and it could automatically update the rendered view when the object changes. We can also create data bindings between different objects (changes in an object would get automatically synchronized to another object). Projects like Flapjax and Fin that have used this approach are clever but have very limited use because they require an interface that doesn’t match with common existing components. By following a consistent pattern throughout Dojo, we can enable this type of live templating in a way that really is useful. Again, these are future ideas, not yet implemented, but the consistent interface makes this very doable.

For now you can begin to use get() and set() methods on all widgets in Dojo 1.5, and create your own watchable objects with dojo.Stateful that can easily be monitored for state changes.