December 9, 2008

ATLAS AJAX Control Toolkit AutoCompleteExtender with Key Lookup

I like the ATLAS AJAX Control Toolkit. It integrates with Visual Studio and has useful if not basic javascript functions that can help a website be much more interactive.

The AutoComplete Extender is used to provide auto-complete functionality to a text box. To use it, you simply add an extender and a web service method that provides a list of strings based on the text that the user started typing. So, if you are trying to provide the exact string that the user is typing (ala google search help), you can use it out of the box.

However, sometimes you want more list-ish functions, that is, you want to present the user with a list of valid choices that represent objects, not just the descriptions. One alternative is to use a Listbox with a ListSearch Extender. This extender is used to find an existing value within the listBox. The downside to this approach is that every item you are looking for has to be in the list. This can be rather unwieldy if the list has more than a couple dozen items.

The other alternative is to use the AutoComplete extender, but have it return a text string and a key that may be used to load the found item. This function is available, but not well documented (or at least where I can find it easily), so, in conformity with the purpose of this blog, I'm putting sample code here.

First of all, we need a hidden field and a text box (with the extender). The bolded properties in the extender point to the web method and the javascript methods that we'll need later.

<asp:hiddenfield id="AccountNumber" runat="server">
<asp:TextBox ID="AccountNumberTextBox" runat="server" Width="20em"/>
<cc1:AutoCompleteExtender ID="AccountNumberTextBox_AutoCompleteExtender"
runat="server" CompletionInterval="200" DelimiterCharacters="" Enabled="True"
FirstRowSelected="True" MinimumPrefixLength="1"
ServiceMethod="GetCompletionList" ServicePath=""
TargetControlID="AccountNumberTextBox" UseContextKey="True"
OnClientItemSelected="AutoCompleteSelected" />

The next thing that has to be done is to return a specially encoded list of label/values in the string array from your web service:
[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string[] GetCompletionList(string prefixText, int count, string contextKey)
myDataContext dc = new DataContext();
var r = (from le in dc.Entities
where (le.AccountNumber.Contains(prefixText) le.Name.Contains(prefixText))
select le).Take(count);
List results = new List();
foreach (var item in r)
string.Format("{0} ({1})", item.Name, item.AccountNumber), item.AccountNumber));
return results.ToArray();

The AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem takes a description and a key value and munges them into a string that can easily parse out the account number.

With that done, we need to add a javascript block to our ASPX that will populate the hidden field with the key value when it is selected from the list.

This script (and constant) do a couple of things. First, we capture the Id of the hidden control so we can use it later to know where to put the id. Next, we disassemble the special text by using the eventArgs.get_Text() and eventArgs.get_Value() functions. These functions are included by the same library that defined our extender.

Add this script to the header section of your page

<script type="text/javascript">
var acctNo = '<%=AccountNumber.ClientId%>';
function AutoCompleteSelected(source,eventArgs)
document.getElementById(acctNo).value = eventArgs.get_value();