AJAX Extender Example: Button Enabled Changes
page 4 of 7
by Brian Mains
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 37425/ 77

Client Component

As I mentioned before, classes go through a registration process that we will see later on.  Registration of a class allows for inheritance. In this example, the client base class that is used with ExtenderControlBase objects is the AjaxControlToolkit.BehaviorBase class. This class inherits from Sys.UI.Behavior defined in the ASP.NET AJAX library, which itself inherits from Sys.Component.

The Sys.Component base class defines some properties that can be used in our client development, most notably:

·         id - Gets the ID of the component; although the ID could be something other than the server control's client ID, the two are usually the same value. This is accessible through get_id().

·         events - Gets the events of the components; events are not defined as you see in the .NET framework, rather the JavaScript library uses a dictionary-based approach to define events.  The object representing events is an object of type EventHandlerList, and we will see how to use it later.

·         raisePropertyChanged - This method, used in conjunction with the INotifyPropertyChanged interface, fires an event, notifying the consumers of the class that the property value changed.

The AJAX Control Toolkit's BehaviorBase class provides additional properties. The clientState property, accessible through get_clientState and set_clientState, represents the value stored in a hidden field, which represents the state of the control (similar to a control's viewstate). Because AJAX components do not have ViewState on the client side (because ViewState is strictly a server mechanism), a hidden field is used as a ViewState mechanism on the client.

Let us get into the code. The shell of the component looks like the following.

Listing 4

Type.registerNamespace("Nucleo.Web.ButtonControls");
//Constructor
Nucleo.Web.ButtonControls.ButtonEnabledExtender = function(associatedElement)
{
  Nucleo.Web.ButtonControls.ButtonEnabledExtender.initializeBase(this,
    [associatedElement]);
 
  this._isEnabledInitially = null;
  this._receiverControlID = null;
 
  this._clickHandler = null;
}
 
//Class definition
Nucleo.Web.ButtonControls.ButtonEnabledExtender.prototype =
{
  …
}
 
//Descriptor
Nucleo.Web.ButtonControls.ButtonEnabledExtender.descriptor =
{
  properties: [..], events: [..]
}
 
//Class registration, registerClass's second parameter is the base class
Nucleo.Web.ButtonControls.ButtonEnabledExtender.registerClass
  ('Nucleo.Web.ButtonControls.ButtonEnabledExtender',
  AjaxControlToolkit.BehaviorBase);
 
if (typeof(Sys) !=  = 'undefined')
  Sys.Application.notifyScriptLoaded();

In the example above, every script registers the namespace it belongs to. Do not worry if you define this multiple times amongst your various scripts; the AJAX framework does not have issues with this. The next definition is the constructor that defines a single parameter: the underlying HTML element being extended. This element is passed to the base class and will be accessible through get_element(). All variables used in the script are also defined in the constructor.

At the end of the script, always register your scripts using the fully quantified name of the class, along with the registerClass method. The registerClass method registers with the system that the ButtonEnabledExtender type is a class that inherits from AjaxControlToolkit.BehaviorBase.

The next section, the prototype, defines the definition of the class. This is where the properties, events and handlers, methods, and lifecycle methods are defined. Remember the properties and events exposed in the server component? Those property values are mapped to the following properties/events below.

Listing 5

get_isEnabledInitially : function()
{
  return this._isEnabledInitially;
},
set_isEnabledInitially : function(value)
{
  if (this._isEnabledInitially != value)
      {
            this._isEnabledInitially = value;
            this.raisePropertyChanged("isEnabledInitially");
      }
},
 
get_receiverControlID : function()
{
      return this._receiverControlID;
},
 
set_receiverControlID : function(value)
{
      if (this._receiverControlID != value)
      {
            this._receiverControlID = value;
            this.raisePropertyChanged("receiverControlID");
      }
},
 
add_enabledStatusChanged : function(handler)
{
      this.get_events().addHandler('enabledStatusChanged', handler);
},
 
remove_enabledStatusChanged : function(handler)
{
      this.get_events().removeHandler('enabledStatusChanged', handler);
},
 
raise_enabledStatusChanged : function()
{
      var eventHandler = this.get_events().getHandler('enabledStatusChanged');
      
      if (eventHandler != null)
            eventHandler(this, Sys.EventArgs.Empty);
},

When the application runs, the IsEnabledInitially and the ReceiverControlID properties on the server side are passed to the set_isEnabledInitially and set_receiverControlID operations on the client-side (because the server component needs to set the values). This happens through a $create static method, but $create is out of the scope of this article.

I mentioned before that there are two lifecycle methods. The initialize method is a key method in this script. Because it is pretty long, I am going to break it up into sections. First, the method calls the initialize method on the base class, as you would using MyBase.New() in VB.NET.

Listing 6

initialize : function()
{
  Nucleo.Web.ButtonControls.ButtonEnabledExtender.callBaseMethod(this, "initialize");
   .
   .
}

Remember that previously I said the extender works in two modes. If the ReceiverControlID property is not null, then the extender toggles the receiving control's disabled status. The first statement of the initialize script processes toggling requests. Normally, the button control contains a script to post back to the server. This needs prevented below; for the time being, I am returning false and clearing the onclick code.

Listing 7

if (this.get_receiverControlID() != null)
{
  if (this.get_element().onclick != null)
  this.get_element().onclick = "return false";
}

The button instance has a click handler, which we want to map to. The click action requires the use of a delegate, which is the purpose of Function.createDelegate below. The delegate is a pointer that maps the JavaScript method clickCallback to the click event of the button. I will discuss clickCallback in a moment; for now, it simply handles the click event.

Listing 8

this._clickHandler = Function.createDelegate(thisthis.clickCallback);
$addHandler(this.get_element(), 'click', this._clickHandler);

Think of a delegate as an intermediary; it simply points the HTML button click event to the clickCallback method. The last step of the initialize method is to retrieve and compare the value stored in client state. If the extender is protecting double-clicking, no processing of client state is needed. Otherwise, client state is used to store the current disabled status of the button.

If client state is present, the current value is passed to the changeStatus method; otherwise, the current status used is pulled from the isEnabledInitially property. Passing in a boolean value signifies that the button should be setting a direct value, and not toggle the value.

Listing 9

if (this.get_receiverControlID() != null)
{
  var clientState =
    Nucleo.Web.ButtonControls.ButtonEnabledExtender.callBaseMethod(this,
    "get_ClientState");
  if (clientState != null)
    this.changeStatus(clientState);
  else
    this.changeStatus(this.get_isEnabledInitially());
}

Another method also uses the changeStatus method: clickCallback. This event fires when the button is clicked, passing in a null value to changeStatus. Null signifies that the button should be toggled.

Listing 10

clickCallback : function(domEvent)
{
  this.changeStatus(null);
},

The changeStatus method is where the core of the work is performed in this script.  Depending on the value passed into the method determines the action to take. If null is passed in, then the enabled status is toggled. If a value is passed in, that value is assigned to the control.

Listing 11

changeStatus: function(isDisabled)
{
  //If no receiver is defined, disable the button after changing the status
  if (this.get_receiverControlID() == null)
  {
    this.get_element().disabled = false;
    return ;
  }
 
  var receiverElement = $get(this.get_receiverControlID());
  if (receiverElement.disabled ==  = "undefined")
    throw new Error.invalidOperation(
      "The receiver control doesn't support disabling");
 
  //If null, toggle the current disabled state
  if (isDisabled == null)
  {
    receiverElement.disabled = !receiverElement.disabled;
    this.raise_enabledStatusChanged();
  }
  else
    receiverElement.disabled = isDisabled;
 
  Nucleo.Web.ButtonControls.ButtonEnabledExtender.callBaseMethod(this,
    'set_ClientState', [receiverElement.disabled]);
}
,

Initially, if the receiver control is null (which means the extender is preventing double clicks), the button is disabled and processing stops. Otherwise, the receiver control is retrieved using the $get helper method (simply a shortcut to document.getElementById). Not every element has a disabled property necessarily, so an error is thrown if it does not.

Notice that the enabledStatusChanged event is fired only when the toggle happens; this occurs when the parameter passed in is null. Otherwise, a direct assignment occurs. The value assigned to the disabled field is stored in client state by using the callBaseMethod method to set the client state.


View Entire Article

User Comments

Title: svfd   
Name: fgdfg
Date: 2012-12-12 7:36:25 AM
Comment:
egte
Title: hello   
Name: hello
Date: 2012-08-22 12:38:27 AM
Comment:
hello
Title: eeee   
Name: aaa
Date: 2012-08-08 2:21:21 AM
Comment:
jjjj
Title: dropdown list   
Name: Vrutti Shah
Date: 2011-11-23 4:47:12 AM
Comment:
I have two dropdown list. I get value of dropdownlist 1 from database. based on the selected value of dropdown 1, dropdown list 2 is populated. I have success in that but problem is that after select value from dropdown 1 page is load and data is lost from another tools like textbox(password type). pls do helpful.
my mail id is:vruttishah1986@gmail.com
Title: Useful information   
Name: pickatutorial.com
Date: 2010-10-05 11:30:12 AM
Comment:
Very useful article. Thanks.
Title: Reply: how to set data in text box based on ajax autocomple   
Name: Brian Mains
Date: 2010-03-11 3:22:38 PM
Comment:
Hello,

Auto complete has a client-side API; you would have to look to see an event that fires when the first text entry is selected, then set the value for textbox2.

HTH.
Title: how to set data in text box based on ajax autocomple   
Name: ieda
Date: 2010-03-10 4:04:46 AM
Comment:
i have two text box.Texbox1 and textbox2.Both use same table in database.Texbox1 use ajax extender autocomplete to select the data. What can i do if i want textbox2 set data aumatically from database after i select data for textbox1?
Title: Re:Button Extender   
Name: Brian
Date: 2008-10-06 3:08:21 AM
Comment:
I tested the code but i cannot achieve your test2 result.
Title: thanks   
Name: Karthikeyan
Date: 2008-09-24 7:54:24 AM
Comment:
Nice article.
Title: thanks   
Name: rezagolab
Date: 2008-09-24 3:10:50 AM
Comment:
hi
thanks
Title: Re:Button Extender   
Name: NamNguyenLe
Date: 2008-08-28 10:15:30 PM
Comment:
Thanks for cool article.
But it will be better if code is avaiable.
Please post it please.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2019 ASPAlliance.com  |  Page Processed at 2019-12-14 4:42:27 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search