Creating the Ajax Component
The Ajax client side code can be added as a part of <script> tag within the web
form. However, since you are creating a component it is better to keep the code
in a separate file. To do so, add a new JScript file to your web site (Figure 7).
[Figure7.jpg]
Figure 7
In the JScript file you will create an Ajax class named AutoSave. Begin by
placing the namespace declaration as shown below:
Type.registerNamespace("AjaxDemos");
The code above declares the AjaxDemos namespace. The AutoSave class you create
further will be part of this namespace. The following code fragment shows the
constructor of the AutoSave class.
AjaxDemos.AutoSave = function (serviceCallback, dataCallback)
{
AjaxDemos.AutoSave.initializeBase(this);
this._interval = 5000;
this._enabled = false;
this._handle = null;
this._serviceCallback = serviceCallback;
this._dataCallback = dataCallback;
}
The code calls the initializeBase() method that invokes the base class constructor.
Recollect from our earlier discussion that the Ajax components inherits from Sys.Component base class.
You also need to declare certain private variables (all that
begin with an _ character are private variables for Ajax) to store interval of
auto save operation and to indicate whether the auto save operation is enabled. The
default interval for auto save operation is set to 5000 milliseconds. The serviceCallback and dataCallback parameters are function references. These
functions will be invoked later to construct an instance of Service class and AutoSaveData
class respectively.
Next comes the prototype of the AutoSave class that contains the properties and
methods. The public properties viz. Interval and Enabled
are shown below:
AjaxDemos.AutoSave.prototype =
{
get_Interval: function () {
return this._interval;
},
set_Interval: function (value) {
if (this._interval != value) {
this._interval = value;
this.raisePropertyChanged("Interval");
this._StopAutoSave();
this._StartAutoSave();
}
},
get_Enabled: function () {
return this._enabled;
},
set_Enabled: function (value) {
if (this._enabled != value) {
this._enabled = value;
this.raisePropertyChanged("Enabled");
if (value)
this._StartAutoSave();
else
this._StopAutoSave();
}
}
The get_Interval and get_Enabled properties are straightforward and need no
explanation. The set_Interval property sets the _interval variable to a new
value and calls the raisePropertyChanged() method supplying the name of the property
being changed. If the client code has wired an event handler to propertyChanged
event of the Sys.Component class you can process this change if needed. The _StopAutoSave() and
the _StartAutoSave() methods (you will code them in a minute)
simply stop and start the auto save operation so that the new interval comes into effect.
The set_Enabled property simply calls the _StartAutoSave() or _StopAutoSave() methods
depending on the boolean value supplied.
AddDataSavingEvantHandler: function (handler) {
this.get_events().addHandler("DataSaving", handler);
},
RemoveDataSavingEvantHandler: function (handler) {
this.get_events().removeHandler("DataSaving", handler);
},
AddDataSavedEvantHandler: function (handler) {
this.get_events().addHandler("DataSaved", handler);
},
RemoveDataSavedEvantHandler: function (handler) {
this.get_events().removeHandler("DataSaved", handler);
}
Next the AutoSave class defines a few methods to add event handlers for two
events viz. DataSaving and DataSaved. The DataSaving event will be raised just
before the auto save operation and DataSaved event is raised after the
auto save operation is over. All the AddXXXX and RemoveXXXX methods shown above
make use of events collection provided by the base class Sys.Component and add
or remove event handler using the addHandler() and the removeHandler() method
respectively.
_RaiseDataSavingEvent: function () {
var handler = this.get_events().getHandler("DataSaving");
if (handler)
handler(this, Sys.EventArgs.Empty);
},
_RaiseDataSavedEvent: function () {
var handler = this.get_events().getHandler("DataSaved");
if (handler)
handler(this, Sys.EventArgs.Empty);
}
The actual task of raising DataSaving and DataSaved events happens inside
_RaiseDataSavingEvent() and _RaiseDataSavedEvent() methods. These methods simply get a reference to the
handler method and invoke it with two parameters viz. object instance and EventArgs. As you can see the event handler looks similar to
standard server side event handlers.
_SaveWork: function () {
this.set_Enabled(false);
this._RaiseDataSavingEvent();
var successCode = Function.createDelegate(this, this._OnSuccess);
var errorCode = Function.createDelegate(this, this._OnError);
var objService = this._serviceCallback();
var objData = this._dataCallback();
objService.SaveWork(objData, successCode, errorCode, null);
},
_OnSuccess: function (result) {
this._RaiseDataSavedEvent();
this.set_Enabled(true);
},
_OnError: function (err) {
alert(err.get_message());
}
The _SaveWork() method is important one as it calls the WCF service created
earlier. Inside this method you first turn off the Enabled property so that next
call to _SaveWork() will not fire unless the previous is finished. DataSaving
event is also raised so that client web form can give some visual notification
to the user. The createDelegate()
method essentially creates a pointer to the code you wish to execute. Doing so
preserves the context for the code being called. Notice the use of _serviceCallback
and _dataCallback function references. The first call returns an instance of the WCF
service proxy class whereas the second call returns an instance of AutoSaveData
class filled with textbox values. You then call SaveWork() method
on the WCF service proxy passing it four parameters. The first parameter is the
actual parameter required by the SaveWork() method on the server. The second
parameter is a JavaScript function that gets called when the operation is
successful. The third parameter represents a JavaScript function that gets
called in case of an error. The last parameter is user context and you
pass it as a null since you don't need it in this example. Notice that since the Ajax
calls remote methods asynchronously the return value of the SaveWork() method is not
available immediately.
The _OnSuccess() method is called when the remote service call returns
successfully and receives a parameter that represents the actual return value of
the remote method that was called. Inside this function you just raise the DataSaved
event and enable the auto save operation again. The _OnError() method is called in case of an error while executing the
remote method. You simply display the error message using the get_message() method of
the error object received as a parameter.
_StartAutoSave: function () {
var code = Function.createDelegate(this, this._SaveWork);
this._handle = window.setInterval(code, this._interval);
},
_StopAutoSave: function () {
if (this._handle) {
window.clearInterval(this._handle);
this._handle = null;
}
}
The _StartAutoSave() method first creates a delegate that points to the _SaveWork()
method. This is done with the help of the createDelegate() method. The setInterval()
method of JavaScript window object is then called passing this delegate and
interval. The setInterval() method is responsible for invoking the saving operation
after a predefined period of time. Notice the use of the _handle variable to store
the returned integer value of the setInterval() method. This value is needed further
in the _StopAutoSave() method.
The _StopAutoSave() method calls the clearInterval() method of the window
object and clears the previously set interval.
dispose: function () {
this.set_Enabled(false);
AjaxDemos.AutoSave.callBaseMethod(this, "dispose");
},
The dispose() method performs some cleanup task such as
disabling the auto save operation and calls the base class dispose() method.
Finally, the AutoSave class you just created is registered with the Ajax
framework.
AjaxDemos.AutoSave.registerClass("AjaxDemos.AutoSave", Sys.Component);
The registerClass() method takes two parameters viz. fully qualified name of
the class being registered and base class (Sys.Component in our case).
Comments
There are no comments yet. Be the first to comment!