Posts Tagged ‘addField’
Adding sweetness to the Microsoft AJAX Library
A few months back, I reviewed some code by a colleague, and I noticed how she used helper functions to generate property accessors in component “classes”. At first I dismissed her approach as unnecessary, but after writing property accessors for the n’th time, I have finally succombed to her way of thinking.
The simplest implementation of a property accessor looks something like this:
MyNamespace.MyComponent = function() {
...
this._myProperty = 12345;
...
}
MyNamespace.MyComponent.prototype = {
...
get_myProperty: function() {
return this._myProperty;
},
set_myProperty: function(value) {
this._myProperty = value;
},
....
}
Wouldn’t it be nice if you don’t have to repeat that code for every property? Well, you can create a Visual Studio code snippet to help with the typing, or add some sugar and write this instead:
MyNamespace.MyComponent = function() {
...
}
MyNamespace.MyComponent.addProperty("myProperty", 12345);
Here is the sugar:
Function.prototype.addField = function(name, value) {
/// <param name="name" type="String"></param>
/// <param name="value" mayBeNull="true"></param>
/// <returns type="String"></returns>
var e = Function._validateParams(arguments, [
{ name: "name", type: String },
{ name: "value", mayBeNull: true }
]);
if (e) throw e;
var fieldName = "_" + name;
if (!(fieldName in this.prototype)) {
this.prototype[fieldName] = value;
}
return fieldName;
}
Function.prototype.addMethod = function(name, method) {
/// <param name="name" type="String"></param>
/// <param name="method" type="Function"></param>
var e = Function._validateParams(arguments, [
{ name: "name", type: String },
{ name: "method", type: Function }
]);
if (e) throw e;
if (!(name in this.prototype)) {
this.prototype[name] = method;
}
}
Function.prototype.addProperty = function(name, initialValue, raisePropertyChanged) {
/// <param name="name" type="String"></param>
/// <param name="initialValue" mayBeNull="true"></param>
/// <param name="raisePropertyChanged" type="Boolean" optional="true"></param>
var e = Function._validateParams(arguments, [
{ name: "name", type: String },
{ name: "initialValue", mayBeNull: true },
{ name: "raisePropertyChanged", type: Boolean, optional: true }
]);
if (e) throw e;
var fieldName = this.addField(name, initialValue);
this.addMethod("get_" + name, function() {
return this[fieldName];
});
if (raisePropertyChanged) {
this.addMethod("set_" + name, function(value) {
if (value !== this[fieldName]) {
this[fieldName] = value;
this.raisePropertyChanged(name);
}
});
} else {
this.addMethod("set_" + name, function(value) {
this[fieldName] = value;
});
}
}
Save this script and include it in your page. Because this script uses JavaScript extensions provided by the Microsoft AJAX Library, please ensure that is included first! I suggest you use <asp:ScriptManager>.
For example:
<asp:ScriptManager runat="server"> <Scripts> <asp:ScriptReference Path="Sugar.js" /> </Scripts> </asp:ScriptManager>
Type.addField(name, value)
Adds a property value field to your component “class”.
For example:
MyNamespace.MyComponent.addField("count", 1);
This is equivalent to:
MyNamespace.MyComponent = function() {
...
this._count = 1;
...
}
Type.addMethod(name, method)
Adds a method to your component “class”.
For example:
MyNamespace.MyComponent.addMethod("sayHello", function (name) {
alert("Hello " + name);
});
This is equivalent to:
MyNamespace.MyComponent.prototype = {
sayHello: function(name) {
alert("Hello " + name);
}
}
Type._addGetter(name, method)
Adds a property getter method to your component “class”. This method is for internal use only!
Type._addSetter(name, method)
Adds a property setter method to your component “class”. This method is for internal use only!
While writing my next post, I decided to factor out the above two “internal” methods, as they don’t add much value.
Type.addProperty(name, initialValue, raisePropertyChanged)
Adds a property to your component “class”. This includes the value field, the getter method and the setter method.
Parameters:
- name – The name of the property, specified as a string in camel case.
- initialValue – The initial value of the property.
- raisePropertyChanged – A boolean to indicate whether you wish to raise the property changed event.
For example:
MyNamespace.MyComponent.addProperty("count", 1, true);
This is equivalent to:
MyNamespace.MyComponent = function() {
...
this._count = 1;
...
}
MyNamespace.MyComponent.prototype = {
...
get_count: function() {
return this._count;
},
set_count: function(value) {
if (value !== this._count) {
this._count = value;
this.raisePropertyChanged("count");
}
},
...
}
Download Sugar.js from my SkyDrive.