WinJS observables (Part II) - manual approach
In my previous blog post I mentioned WinJS observables and their usage and pitfalls. There are several alternative implementations which could help us to overcome that issues. Let's see first of them.
Goal
Just repeat what's our goal in BDD style:
AS a developer
I WANT to be able to define observable properties on the class as well as other class parts: get/set properties and methods and I don't want to pay any unnecessary performance penalties
SO THAT the observable object will be able to notify listeners that the property has changed
Solution
In this blog post we'll look at the manual approach. We need to do two things:
- ensure that the class has all required methods and fields needed for being observable
- wrapping the property with the observable functionality There are mixins which define the required methods and fields.
So the first requirement can be solved by defining a base class with all mixins
var ObservableBase = WinJS.Class.mix(function () {
}, WinJS.Utilities.eventMixin, WinJS.Binding.mixin);
The second requirement can be solved by defining the helper method:
function observableProperty(name, defValue) {
var backingName = "_" + name;
return {
get: function getter() {
if (!(backingName in this)) {
return defValue;
}
var currentValue = this[backingName];
return currentValue;
},
set: function setter(newValue) {
var oldValue = this[backingName];
if (oldValue !== newValue) {
this[backingName] = newValue;
this.notify(name, newValue, oldValue);
}
}
};
}
So let's put the things together:
var Person = WinJS.Class.derive(ObservableBase, function () {
}, {
name: observableProperty("name", "Frantisek Kaduk"),
_year: 1234
});
Deriving from ObservableBase class ensures that new class has all mixins imported and observableProperty helper function creates property definition with get/set wrapper methods. The most important is the "set" method. This method makes sure that when the value has changed all listeners are notified (calling method notify).
Let's use it:
var person = new Person();
person.bind("name", function (v) {
WinJS.log("name has changed to " + v, "person");
});
person.name = "Fero Kaduk";
Running the above code generates the following output:
person: name has changed to Frantisek Kaduk <= initial value
person: name has changed to Fero Kaduk
The complete sample is attached to the blog post.
Summary
The manual solution has the following disadvantages.
- It forces the developer to derive from ObservableBase class.
- observable property is handled manually
So let's see another solution in the next post.