Click here to Skip to main content
5,786,882 members and growing! (22,129 online)
Email Password   helpLost your password?
Web Development » Ajax and Atlas » Samples     Intermediate License: The Code Project Open License (CPOL)

Implementing google like suggestion using autocomplete extender

By Zafar.Iqbal

How to use autocomplete extender to provide contact suggestion
C# (C# 2.0, C#), Javascript, CSS, XHTML, HTML, .NET (.NET, .NET 2.0), ASP.NET, WebForms, Ajax, Dev

Posted: 24 Jun 2008
Updated: 24 Jun 2008
Views: 13,509
Bookmarked: 25 times
Note: This is an unedited reader contribution
Announcements
Loading...



Search    
Advanced Search
Sitemap
5 votes for this Article.
Popularity: 2.64 Rating: 3.78 out of 5
0 votes, 0.0%
1
1 vote, 20.0%
2
0 votes, 0.0%
3
2 votes, 40.0%
4
2 votes, 40.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

This sample demonstrate, how you can use AutoCompleteExtender control from ASP.NET AJAX Control Toolkit and customize its behavior without modifying it.

Background

I like Google's suggest feature and was thinking of using it in any of my project. ASP.NET's AJAX Control Toolkit have a similar control (AutoCompleteExtender) which provides a basic items to complete this functionality. I searched about its usage, and found many examples, but I was not satisfied with them. They all were populating only a single field using this extender.

I then came up with an idea, why not fill a contacts detail including its name, email address, and phone numbers using just one extender, but without modifying any provided functionality, so that our code be used with newer versions. Below is what it will look after populating that contact form.

AutoSuggest

Using the code

Lets checkout how AutoCompleteExtender works. Below is the description for this on toolkit's sample site.


AutoComplete is an ASP.NET AJAX extender that can be attached to any TextBox control, and will associate that control with a popup panel to display words that begin with the prefix typed into the textbox.

The dropdown with candidate words supplied by a web service is positioned on the bottom left of the text box.


It says that this control will fetch its data from a webservice, and it can be attached to a TextBox control (it can only be attached with one control). When users starts typing in that TextBox control, it fetches a suggestion list from configured webservice.

So we need two things, one would be our sample contact page, and another a webservice. Here is our webservice code.


using System;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Web.Script;
using System.Web.Script.Serialization;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.Services.Protocols;
using AjaxControlToolkit;


/// 
/// Summary description for SuggestionService
/// 
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class SuggestionService : System.Web.Services.WebService {

    public SuggestionService () {

        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    [WebMethod]
    [ScriptMethod()]
    public string[] GetContacts(string prefixText, int count, string contextKey) {
        List items = new List();
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        ContactManager manager = new ContactManager();
        List contacts = manager.GetContacts(int.Parse(contextKey), prefixText, count);
        foreach (Contact c in contacts)
        {
            items.Add(AutoCompleteExtender.CreateAutoCompleteItem(c.FullName, serializer.Serialize(c)));
        }

        return items.ToArray();
    }
    
}

You will notice some extra adornments on service and web method. You must adorn this service with "ScriptService" attribute, because without it, you can not access it from your client script.

[ScriptService()]
public class SuggestionService : System.Web.Services.WebService {

And our webmethod would return list of string items in JSON format, so it also requires ScriptMethod attribute on it.

    [WebMethod]
    [ScriptMethod()]
    public string[] GetContacts(string prefixText, int count, string contextKey) {}

In addition to that you have also noticed that I have returned this data differently. I have used AutoCompleteExtender to create its own entries, because I want to return some extra data from my webservice, so that I can populate all related fields on my contact form. This feature is only available in latest build of AJAX Control Toolkit (1.0.20229.0). It was not available before that. It provides a key-value pair, which is a very useful feature, if we want to display a list of friendly names against internal ids. CreateAutoCompleteItem method takes two argument, first is the text which will be displayed and second is the value which can be used by any custom script on the page.

            items.Add(AutoCompleteExtender.CreateAutoCompleteItem(c.FullName, serializer.Serialize(c)));

Now I had another obstacle to overcome, how to pass a complex data for a contact. Here comes JSON for my help. I serialized my contact objects using JavaScriptSerializer.

So far I have bragged that my contact object is a bit complex, here is what it looks like. Below is my Contact and Phone classes.

/// 
/// Summary description for Contact
/// 
public class Contact
{
    protected int _contactId;
    public int ContactId
    {
        get { return _contactId; }
    }

    protected int _companyId;
    public int CompanyId
    {
        get { return _companyId; }
        set { _companyId = value; }
    }

    protected string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }

    protected string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; }
    }

    public string FullName
    {
        get { return _firstName + ' ' + _lastName; }
    }

    protected string _email;
    public string Email
    {
        get { return _email; }
        set { _email = value; }
    }
    public int _homePhoneId;
    public int _workPhoneId;

    protected Phone _homePhone;

    public Phone HomePhone
    {
        get { return _homePhone; }
        set { _homePhone = value; }
    }
    protected Phone _workPhone;

    public Phone WorkPhone
    {
        get { return _workPhone; }
        set { _workPhone = value; }
    }


    public Contact() : this(0, 0, 0)
    {
    }

    public Contact(int id) : this(id, 0, 0)
    {
    }

    public Contact(int id, int homephone, int workphone)
    {
        _contactId = id;
        _homePhoneId = homephone;
        _workPhoneId = workphone;
    }
}

/// 
/// Summary description for Phone
/// 
public class Phone
{
    protected int _phoneId;
    public int PhoneId
    {
        get { return _phoneId; }
    }

    protected string _areaCode;
    public string AreaCode
    {
        get { return _areaCode; }
        set { _areaCode = value; }
    }

    protected string _prefix;
    public string Prefix
    {
        get { return _prefix; }
        set { _prefix = value; }
    }

    protected string _number;
    public string Number
    {
        get { return _number; }
        set { _number = value; }
    }

    protected string _extension;
    public string Extension
    {
        get { return _extension; }
        set { _extension = value; }
    }

    public Phone() : this(0)
    {
    }

    public Phone(int id)
    {
        _phoneId = id;
    }
}

Now we have to work out on our contact page. Below is its basic HTML, this contact form contains, firstname, lastname, email address, and phone number fields. Each phone number in-turn have prefix, area code, number and extension fields.

       <div style="border: 1px solid rgb(204, 204, 204); padding: 10px; width: 400px;">
            <table cellspacing="0" cellpadding="0" border="0">
                <tbody><tr>
                    <td style="width: 100px; text-align: right;">First Name:</td>
                    <td><asp:textbox runat="server" id="txtFirstName" /></td>
                </tr>
                <tr>
                    <td style="width: 100px; text-align: right;">Last Name:</td>
                    <td><asp:textbox runat="server" id="txtLastName" /></td>
                </tr>
                <tr>
                    <td style="width: 100px; text-align: right;">Home Phone:</td>
                    <td>
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody><tr>
                                <td><asp:textbox columns="3" runat="server" id="txtHPAreaCode" /></td>
                                <td>-<asp:textbox columns="3" runat="server" id="txtHPPrefix" /></td>
                                <td>-<asp:textbox columns="3" runat="server" id="txtHPNumber" /></td>
                            </tr>
                        </tbody></table>
                    </td>
                </tr>
                <tr>
                    <td style="width: 100px; text-align: right;">Work Phone:</td>
                    <td>
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody><tr>
                                <td><asp:textbox columns="3" runat="server" id="txtWPAreaCode" /></td>
                                <td>-<asp:textbox columns="3" runat="server" id="txtWPPrefix" /></td>
                                <td>-<asp:textbox columns="3" runat="server" id="txtWPNumber" /></td>
                                <td> x </td>
                                <td><asp:textbox columns="3" runat="server" id="txtWPExtension" /></td>
                            </tr>
                        </tbody></table>
                    </td>
                </tr>
                <tr>
                    <td style="width: 100px; text-align: right;">Email Address :</td>
                    <td><asp:textbox runat="server" id="txtEmail" /></td>
                </tr>
            </tbody></table>
        </div>
 

To use AutoCompleteExtender on this page, first place a ScriptManager control, and then place AutoCompleteExtender control and set its TargetControlId to firstname TextBox control. This will add some extra properties in firstname TextBox control. These properties are related to its attached extender, you can find there description on AutoCompleteExtender sample page. We must set some of them to activate its working.

First specify the ServicePath and set it to our webservice we just created and then set the ServiceMethod, which will return list of suggestions, this would be our webmethod in our service. We could also use context key, which can help us in filtering our suggestions. In our case I have used it to pass current company information, so that I can return a particular company's contacts.

This completes our basic setup. If you test this page now, you will get a suggestion list after typing two letters in firstname field, and when you select any item from that list, only firstname field is set with selected name. All other fields would remain blank.

Now we need to add our magic code, which will enable us to achieve our goal.

    <script type="text/javascript">
        function OnContactSelected(source, eventArgs)
        {
            var results = eval('('  + eventArgs.get_value() + ')');
            $get('txtFirstName').value = results.FirstName;
            $get('txtLastName').value = results.LastName;
            if (results.HomePhone.AreaCode != null)
                $get('txtHPAreaCode').value = results.HomePhone.AreaCode;
            if (results.HomePhone.Prefix != null)
                $get('txtHPPrefix').value = results.HomePhone.Prefix;
            if (results.HomePhone.Number != null)
                $get('txtHPNumber').value = results.HomePhone.Number;
            if (results.WorkPhone.AreaCode != null)
                $get('txtWPAreaCode').value = results.WorkPhone.AreaCode;
            if (results.WorkPhone.Prefix != null)
                $get('txtWPPrefix').value = results.WorkPhone.Prefix;
            if (results.WorkPhone.Number != null)
                $get('txtWPNumber').value = results.WorkPhone.Number;
            if (results.WorkPhone.Number != null)
                $get('txtWPExtension').value = results.WorkPhone.Extension;
            if (results.Email != null)
                $get('txtEmail').value = results.Email;
        }
    </script>
  

But before that we need to add some client-side behavior to our extender, we need to set OnClientItemSelected attribute of our extender to above javasript function. This function would parse the value attribute, which is a valid JSON data passed from our webservice, and set appropriate fields with this parsed data.

This conclude our sample, now you can test it yourself.

History

  • 2008-06-24 - My first attempt on ajax auto extensions

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Zafar.Iqbal


Zafar Iqbal had a first taste of computing while taking a course on computer languages way back in 1995. He started programming in Quick Basic, that was the love at first sight.

Then he completed his masters in Computer Science, and started his job in late 2000.

Since then he has been fully engrossed in application development ranging from office automation system, business application, web development, and lot of other things.

His core programming languages are VB.NET and C#, but he is also comfortable in Java.

Last 5 years had made him strong in web development, mostly using ASP.NET, which also includes (X)HTML, XML, XSLT, Javascript, CSS and other related technologies.

You can view my profile on LinkedIn and I also mutter sometime here "Dessey Cow"
Occupation: Web Developer
Company: Trisoft Technologies
Location: Pakistan Pakistan

Other popular Ajax and Atlas articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 8 of 8 (Total in Forum: 8) (Refresh)FirstPrevNext
GeneralWhat worked for mememberveaudoo19hrs 50mins ago 
GeneralRe not workingmemberHeval23:21 10 Aug '08  
GeneralNot working in 2005memberasifmehdi20:46 8 Aug '08  
GeneralRe: Not working in 2005memberZafar.Iqbal20:48 10 Aug '08  
QuestionHelp PleasememberHeval15:43 8 Aug '08  
GeneralAutoExtender not firing.memberracer81x4:29 7 Jul '08  
GeneralRe: AutoExtender not firing.memberZafar.Iqbal20:40 7 Jul '08  
GeneralRe: AutoExtender not firing.memberhenrim.nor23:28 2 Dec '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Jun 2008
Editor:
Copyright 2008 by Zafar.Iqbal
Everything else Copyright © CodeProject, 1999-2009
Web15 | Advertise on the Code Project