The blog of dlaa.me

AutoComplete++ [How to: Create a multi-word auto-complete text box]

By default, the AJAX Control Toolkit's AutoComplete extender doesn't have a notion of "words" and will try to auto-complete whatever text is currently in the text box, treating what's there as a single "word". One request that has come up a few times was for the ability to auto-complete multiple words individually. According to the comments of that work item, it looks like someone's made a set of proposed changes to do just that! It's great to have such an involved user community!! (Please note: The work item comments suggest those changes don't work in all browsers.)

One thing I'd been meaning to do was write a quick sample of how to get reasonably good multiple-word auto-complete without making any modifications to the released AutoComplete extender. In other words, you can use the latest official Toolkit release (10301 in this case) and get some nice multi-word completion today. The key observation here is that the Web Service used to provide the list of candidate words has all the information it needs to do multi-word completion as well:

Multi-word auto-complete example

The complete code for the sample page is included below for anyone to look at or modify for their purposes. A few notes about the code:

  • The example was written to be simple, not efficient. The goal is to demonstrate the idea as plainly as possible, so there's no focus on performance.
  • The code works by auto-completing the last "word" of input and then populates the list of candidates with the resulting words and the preceding text.
  • All comparisons are case-insensitive so the user can type however they want.
  • In a real-world application, the list of candidate words would probably be retrieved from a helper function, a database, etc..

Here's the complete ASPX file:

<%@ Page Language="C#" %>

<%
@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit"
    TagPrefix="ajaxToolkit" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<
script runat="server">
    [System.Web.Services.WebMethod]
    [System.Web.Script.Services.
ScriptMethod]
    
public static string[] GetCompletionList(string prefixText, int count)
    {
        
// Fetch and sort the list of available completion words
        string[] allWords = "AJAX Control Toolkit AutoComplete auto automatic".Split(' ');
        
Array.Sort(allWords);

        
// Split input into completed words and prefix characters for the current word
        // Match on the current word and return candidate list including completed words
        // Ex: "he" -> "" and "he..."
        // Ex: "hello there th" -> "hello there " and "th..."
        string completedWords = "";
        
string prefixChars = prefixText;
        
int lastSpace = prefixText.LastIndexOf(' ');
        
if (-1 != lastSpace)
        {
            completedWords = prefixText.Substring(0, lastSpace + 1);
            prefixChars = prefixText.Substring(lastSpace + 1);
        }

        
// Create the completion list by searching for prefix matches
        System.Collections.Generic.List<string> completionList =
            
new System.Collections.Generic.List<string>();
        
foreach (string word in allWords)
        {
            
if (word.ToUpperInvariant().StartsWith(prefixChars.ToUpperInvariant()))
            {
                completionList.Add(
string.Concat(completedWords, word));
            }
        }

        
// Return the completion list
        return completionList.ToArray();
    }
</script>

<
html xmlns="http://www.w3.org/1999/xhtml">
<
head runat="server">
    <title>Multi-Word Auto-Complete</title>
</
head>
<
body>
    <form id="form1" runat="server" onsubmit="return false;">
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
        <asp:TextBox ID="TextBox1" runat="server" Width="300" />
        <ajaxToolkit:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server"
            TargetControlID="TextBox1" ServiceMethod="GetCompletionList"
            MinimumPrefixLength="0" />
    </form>
</
body>
</
html>

Enjoy!