Thursday, March 06, 2008

Using the AjaxControlToolkit AutoCompleteExtender - Part 2

A while ago I wrote a quick post to remind me of how to use the AutoCompleteExtender, but recently I realised that it was terribly incomplete (pun not intended). I've updated it, but I also felt that I need to restructure the whole post, so here it is, with more details and more code fun.

First of all, a short disclaimer: I am not familiar with the ASP.Net Ajax javascript paradigm. If some of the things that I am doing seem really stupid, it's because I did it by trial and error, not by understanding why the code is as it is. Here it goes.

There are two ways in which to use the AutoCompleteExtender: using PageMethods or using web service methods. The details are in the previous post, I will only list the gotchas in this one.
  • PageMethods requirements:
    1. ScriptManager must have EnablePageMethods="true"
    2. The page method must have the form public static string[] MethodName(string prefixText, int count) AND THE SAME PARAMETER NAMES. If you change prefixText with text it will not work!
    3. The page method has to be public and STATIC
    4. No, it is not possible to declare the method in a web user control, it must be in the page
  • Web service requirements:
    1. The method must have the form public string[] MethodName(string prefixText, int count) AND THE SAME PARAMETER NAMES. If you change prefixText with text it will not work!
    2. The method has to be public and NOT STATIC
    3. The method must be marked as ScriptMethod

Now, the method can return an array different from a string array, but the only useful types there would be numerical or maybe dates. Any object that you send will ultimately be transformed into "[object Object]". There is a way to send a pair of value,text encoded in the strings, and for that you use:
AutoCompleteExtender.CreateAutoCompleteItem(text, value);

It doesn't help much outside the fact that in the client javascript events of the AutoCompleteExtender the first parameter will be the AutoCompleteExtender javascript object and the second an object with a _text and a _value properties.

One of the questions I noticed frequently on the web is: How do I show the user that there are no auto complete matches?. The easy solution is always to return at least one string in the string array that your method is returning. If there are no matches, make sure there is a "No Match" string in the list. But then the complicated part comes along: how do you stop the user from selecting "No Match" from the list? And I do have a solution. It seems that the text in the textbox is set based on the existence of a javascript object called control that has a set_text function. If the object or the function do not exist, then a simple textbox.value=text is performed. So I used this code:

string script = @"var tb=document.getElementById('" + tbAutoComplete.ClientID + @"');if (tb) tb.control={set_text:setText,element:tb};";
to set the object for my textbox. And also the javascript code that looks liks this:
function setText(input) {
if (input=='No Match') return;

These being said, I think that one can use the AutoCompleteExtender and know what the hell is making it not work.


Anonymous said...

Sorry I am leaving this question as a comment. Hoping i could get the anser from your blog.

Could you please let me know how exactly the request is processed when using the autocomplete extender for a textbox.

For example:

Starting from the key press which event is called after the pagemethod or the webservicemethod is executed.

The reason I am asking this question is .. I have a situation where there is a Textbox with autcomplete extender and when I try to copypaste some text I am getting the result item..but i m not able to capture that value in OnClientPopulated event.

Could you please suggest me which client event can be used to capture that event or is it wrong to expect this functionality.

Siderite said...

No problem for posting the question, but I haven't been working with these controls for a long time now. I couldn't really answer you with any certainty. Best to follow the code in their Javascript files (which you can find in the sources for ACT) and see how they do things.