• Autocomplete in asp.net with images and formatting

    Before jQuery, I used AJAX Control Toolkit and I liked it as it contained lots of helpful widgets. With jQuery there are now much more options how to implement something. Today I searched for something like the autocomplete so you could type in the first letters and then get some proposals. We all know this from Google  etc. Some sides also have formatting in the result list, e.g. at Telerik, or also show images. So let’s see whether we could do the same for asp.net.

    Requirements

    In most of my projects I use jQuery, jQueryUI and Bootstrap. Maybe we could build it with just these 3 scripts. jQueryUI has an autocomplete option. This might be a good start.

     

    jQuery Data Retrieval

    Data Retrieval is of course done via a Webservice which is explained below. When data is returned, the content is copied into internal variables so we could use them later on when we setup the display format. As in previous example I used Name, ID, Additional Info and Image but of course you are free to add whatever you want. Don’t forget to update the function in the success-section of the Ajax-Script.

    Styling

    For the formatting we use the autocomplete-option as explained in jQueryUI custom data example . Additionally I’ve added some very basic CSS formatting using the classes username, userimage and userinfo just to show how it works. The rest is formatted by jQueryUI and Bootstrap.

     

    Store user selection

    Once we select a name, we want to display the username in the textbox but also keep the unique ID for later processing because e.g. a username might exist twice but the ID is unique. Therefore the select-event not just updates the textbox but it also stores the userid in our hidden field SelectedUserID.

     

    Webservice Data Retrieval

    The data retrieval in the example is very easy: I hardcoded a table with some usernames. In the live project we have some database where the data is retrieved on the fly but for this example I kept it as simple as possible. So we have a select-statement which uses the supplied user input. A new instance of class UserDetails is created and filled with the returned data. If you want to restrict the maximum number of return results you should filter using LINQ or a statement (SELECT TOP 2 …) accordingly. Additionally there are several ways of providing the JSON result. I’ve decided to use a dedicated class as this might be easier to understand. Of course you are free to use other methods.

     

    The Code

    As usual here is the full source code so you could easily build it on your own.

    Autocomplete.aspx

     

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="AutoComplete.aspx.vb"
        Inherits="WebApplication1.AutoComplete" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <head runat="server">
        <script src="//code.jquery.com/jquery-1.11.0.min.js" type="text/javascript"></script>
        <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
        <title></title>
        <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js" type="text/javascript"></script>
            rel="Stylesheet" type="text/css" />
        <style>
            .username
            {
                display: block;
                font-weight: bold;
                margin-bottom: 1em;
            }
            .userimage
            {
                float: left;
                max-height: 50px;
                max-width: 50px;
                margin-right:10px;
            }
            .userinfo
            {
                margin: 0;
                padding: 0;
            }
        </style>
        <script type="text/javascript">
            $(document).ready(function () {
                $("#<%=SelectedUsername.ClientID %>").autocomplete({
                    source: function (request, response) {
                        $.ajax({
                            url: '<%=ResolveUrl("~/Webservices/WebService1.asmx/GetUsers") %>',
                            data: "{ 'input': '" + request.term + "'}",
                            dataType: "json",
                            type: "POST",
                            contentType: "application/json; charset=utf-8",
                            success: function (data) {
                                response($.map(data.d, function (item) {
                                    return {
                                        username: item.Username,
                                        userid: item.UserID,
                                        info: item.AdditionalInfo,
                                        image: item.ImageURL
                                    }
                                }))
                            }
                        });
                    },
                    minLength: 1,
                    select: function (event, ui) {
                        $("#<%=SelectedUsername.ClientID %>").val(ui.item.username);
                        $("#<%=SelectedUserID.ClientID %>").val(ui.item.userid);
                        return false;
                    }
                })
                             .autocomplete("instance")._renderItem = function (ul, item) {
                                 return $("<li>")
                                .append("<a><img class='userimage' src='" + item.image + "' class='img-rounded' />")
                                .append("<p class='username'>" + item.username + "</p>")
                                .append("<p class='userinfo'>" + item.info + "</p></a>")
                                .appendTo(ul);
                             };
            });
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
        <div style="margin: 100px">
            <asp:TextBox ID="SelectedUsername" runat="server"></asp:TextBox>
            <asp:HiddenField ID="SelectedUserId" runat="server" />
            <asp:Button ID="Process" runat="server" Text="Do whatever" />
        </div>
        </form>
    </body>
    </html>

    Autocomplete.aspx.vb

     

    Public Class AutoComplete
        Inherits System.Web.UI.Page
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        End Sub
        Private Sub btnSubmit_Click(sender As Object, e As System.EventArgs) Handles Process.Click
            Dim selectedName As String = SelectedUsername.Text
            Dim selectedID As String = SelectedUserId.Value
        End Sub
    End Class

    Webservice1.asmx.vb

     

    Imports System.Web.Services
    Imports System.Web.Services.Protocols
    Imports System.ComponentModel
    ' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    <System.Web.Script.Services.ScriptService()> _
    <System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
    <System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
    <ToolboxItem(False)> _
     Public Class WebService1
        Inherits System.Web.Services.WebService
        Public Class UserDetails
            Public Username As String
            Public UserID As String
            Public ImageURL As String
            Public AdditionalInfo As String
        End Class
        <WebMethod()> _
       <Script.Services.ScriptMethod(ResponseFormat:=Script.Services.ResponseFormat.Json)> _
        Public Function GetUsers(ByVal input As String) As List(Of UserDetails)
            Dim dt As DataTable = CreateDatatable()
            Dim rows As DataRow()
            rows = dt.Select(String.Format("Username like '%{0}%'", input))
            Dim result As New List(Of UserDetails)
            For Each row In rows
                Dim r As New UserDetails
                r.Username = row("Username")
                r.UserID = row("UserID")
                r.ImageURL = row("ImageURL")
                r.AdditionalInfo = row("AdditionalInfo")
                result.Add(r)
            Next
            Return result
        End Function
        Private Function CreateDatatable() As DataTable
            Dim dt As New DataTable
            dt.Columns.Add("UserID")
            dt.Columns.Add("Username")
            dt.Columns.Add("ImageURL")
            dt.Columns.Add("AdditionalInfo")
            Dim row As DataRow
            row = dt.NewRow
            row("UserID") = "ZuckerbergM"
            row("Username") = "Mark Zuckerberg"
            row("AdditionalInfo") = "Co-Founder of Facebook"
            dt.Rows.Add(row)
            row = dt.NewRow
            row("UserID") = "MuskE"
            row("Username") = "Elon Musk"
            row("AdditionalInfo") = "CEO of SpaceX and Tesla Motors"
            dt.Rows.Add(row)
            row = dt.NewRow
            row("UserID") = "GatesB"
            row("Username") = "Bill Gates"
            row("AdditionalInfo") = "Co-Founder of Microsoft"
            dt.Rows.Add(row)
            row = dt.NewRow
            row("UserID") = "DorseyJ"
            row("Username") = "Jack Dorsay"
            row("AdditionalInfo") = "Co-Founder of Twitter"
            dt.Rows.Add(row)
            Return dt
        End Function
    End Class

     

     

Leave a comment

If you want to share your opinion, leave a comment.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">