Wednesday, March 21, 2012

How To Handle OnChange / SelectedIndexChanged Type Event In JavaScript For The AJAX ComboBox

If you have ever used the AJAX ComboBox control and needed to interact with it client side in JavaScript, you will notice it's a bit of a different animal than it's ASP.NET server control counterpart: the DropDownList. If you want to get either the selected text or its value from a traditional DropDownList, all you needed to do was add an JavaScript function call to the 'onchange' client side property on the control like below:
<asp:DropDownList ID="AspNetDDL1" runat="server" AppendDataBoundItems="true" 
onchange="dropDownListOnChange(this);">
<asp:ListItem Text="( Select a Color )" Value="0" />
<asp:ListItem Text="Red" Value="1" />
<asp:ListItem Text="White" Value="2" />
<asp:ListItem Text="Blue" Value="3" />
</asp:DropDownList>
The JavaScript method for getting the value from an ASP.NET DropDownList is just as trivial as shown below. It will fire the alert each time a valid selection is made.
function dropDownListOnChange(sender) {
if (sender.value = 1) {
alert('You selected Red!');
}
else if (sender.value = 2) {
alert('You selected White!');
}
else if (sender.value = 3) {
alert('You selected Blue!');
}
}
However the AJAX ComboBox is a bit different and not just some user control inheriting from the ASP.NET DropDownList with all of the same properties and events. The AJAX ComboBox is built from the ground up, and when rendered to the client is comprised of (4) main parts:

- A text box showing the selected item.
- A button to press to show the list (usually a down arrow)
- An unordered list with all of the items bound.
- A hidden field with the selected value.

Now the common misconception is to try and handle client side events on the textbox or the unordered list like 'blur', 'keydown', 'keyup', 'change', or 'mousemove'. The problem is none of the events used individually or collectively (jQuery allows binding to multiple events easy) work perfectly. It requires the user to tab off the field, move the mouse, or some other action before the JS function gets called. That's not ideal at all as the selection from the ComboBox might be the only control on a page, or the last one on a page, and the client doesn't do any of the actions required. If for example the result of your wired up JS function is to show/hide other controls, then you want the JS function to fire immediately without delay and as it should.

The answer lies in some 'hard to find' documented events that can have functions assigned to handle these events. Specifically for this topic we are speaking of the add_propertyChanged event handler. We need to wire up this handler to our AJAX ComboBox client side which will then allow us to get the selected item or value client-side without having to make an expensive server trip. The documentation on the event handler is below:

Sys.Component.propertyChanged Event

As a side note, always keep this advice in mind. If you are a web developer and especially an ASP.NET webforms developer, it's all too easy to get lazy and inefficient by doing everything server-side. Why? Because you can! And how do we masquerade expensive server trips? With AJAX UpdatePanels, yeah! Don't get me wrong, I really like asynchronous postbacks with UpdatePanels and use them often, but make sure to use them when you actually need to go server side to make a call. If you make a dropdownlist, radio button, checkbox, or other server control go server side just to show another hidden row, add a control, or change some visual state, then you are bloating the time it takes to run your code and making a bad choice but not handling things that can take place 100% client side on the client. With all the JS explosion recently with libraries like jQuery there is no reason not to handle these types of needs client side.

Back on the AJAX ComboBox, we need to assign a function to the add_propertyChanged event handler on our control. Remember to get the ClientID of the value for server controls, as you cannot just pass in the raw ID.
function AJAXComboBox1_Change() {
//Add event to ui_ddlStrategicObjective AJAX Combobox:
$find('<%=AJAXComboBox1.ClientID %>').add_propertyChanged(function (sender, e) {
if (e.get_propertyName() == 'selectedIndex') {
//Gets the selected index from the HiddenField associated with the AJAX Combobox control.
var selectedIndex = sender.get_hiddenFieldControl().value;
////Gets the selected text from the AJAX ComboBox
var selectedText = sender.get_textBoxControl().value;

//Just sample JS code - you could do anything here:
//show/hide controls, alerts, change client settings, etc.
if (sender.value = 1) {
alert('You selected Red!');
}
else if (sender.value = 2) {
alert('You selected White!');
}
else if (sender.value = 3) {
alert('You selected Blue!');
}
}
});

//AJAX's pageLoad function automatically provides a handler for the 'load' event
function pageLoad() {
//Make call to handle selection changes to the 'AJAXComboBox1' AJAX Combo Box
AJAXComboBox1_Change()
}
Take notice above how we call our new function 'AJAXComboBox1_Change' in pageLoad(). You cannot interact with a control until it has been initialized (i.e. you cannot call add_propertyChanged on a control unless the control actually exists). A control does not exist until the initialization phase of the ASP.NET AJAX framework is complete. We can use AJAX's 'pageLoad()' method as this script needs to be ran during postbacks and partial postbacks is using UpdatePanels. The pageLoad function automatically provides a handler for the 'load' event. You can read about AJAX Client Events in the link below.

ASP.NET AJAX Client Life-Cycle Events

In conclusion there are a few 'big picture' points to make about this entry. First and foremost, when doing web development, try and make your applications as efficient as possible by doing operations client side that don't need to be done on the server (even if they can be done that way).

Second, the AJAX ComboBox may not be a widely used control going forward because its main draw which is the JS support for typing in values and quickly selecting them has been superseded in my opinion by things like the jQuery AutoComplete extender. Dropdowns in general are probably a good choice for the 1-25ish item range, but anything more bloats the page size. In this case making async callbacks to get values real time (like with the jQuery autocomplete) is a better idea. However, it does not mean there aren't a ton of apps already using the AJAX ComboBox, and the need to interact with it client side may present itself someday. If this 'someday' comes up (which it usually does), you will now be prepared to capture its values in JavaScript.

No comments:

Post a Comment