AutoComplete DropDownList Alternatives In ASP.NET

There are alternate ways to implement autocomplete dropdown/textbox component in your Website. One option is to implement Chosen: A jQuery Plugin by Harvest to Tame Unwieldy Select Boxes

For this, you need to bind the dropdownlist in a similar way; it is done and configured when choosing a plugin over the dropdownlist control. Here is a sample auto complete dropdownlist, using chosen plugin. It also allows you to give selected items on Postbacks on the code at the back-end.

  1. <!DOCTYPE html>  
  2.   
  3. <html xmlns="http://www.w3.org/1999/xhtml">  
  4. <head runat="server">  
  5.     <title></title>  
  6.     <link href="Content/chosen.min.css" rel="stylesheet" />  
  7.     <script src="Scripts/jquery-1.12.4.min.js"></script>  
  8.     <script src="Scripts/chosen.jquery.min.js"></script>  
  9.     <script type="text/javascript">  
  10.         $(document).ready(function () {  
  11.             InitDropDown();  
  12.         })  
  13.   
  14.         function InitDropDown() {  
  15.             var config = {  
  16.                 '.ChosenSelector': { allow_single_deselect: true, search_contains: true, width: "350px" },  
  17.             }  
  18.             for (var selector in config) {  
  19.                 $(selector).chosen(config[selector]);  
  20.             }  
  21.         }  
  22.     </script>  
  23. </head>  
  24. <body>  
  25.     <form id="form1" runat="server">  
  26.         <asp:DropDownList   
  27.             runat="server"   
  28.             ID="ddlDropDown"   
  29.             DataTextField="EmpName"   
  30.             DataValueField="EmpId"  
  31.             CssClass="ChosenSelector"  
  32.             data-placeholder="Select Employee"  
  33.             AppendDataBoundItems="true">  
  34.             <asp:ListItem Text="" Value="-1"></asp:ListItem>  
  35.         </asp:DropDownList>  
  36.     </form>  
  37. </body>  
  38. </html>  
The code is given at the back-end to bind dropdownlist.
  1. protected void Page_Load(object sender, EventArgs e)  
  2. {  
  3.     if (!IsPostBack)  
  4.     {  
  5.         BindDropdown();  
  6.     }  
  7. }  
  8.   
  9. //-- bind dropdown  
  10. private void BindDropdown()  
  11. {  
  12.     DataTable dtAutoCompleteSrc = GetSampleData();  
  13.     ddlDropDown.DataSource = dtAutoCompleteSrc;  
  14.     ddlDropDown.DataBind();  
  15. }  
  16.   
  17. //-- generate sample data for auto complete  
  18. private DataTable GetSampleData()  
  19. {  
  20.     DataTable dtAutoCompleteSrc = new DataTable();  
  21.     dtAutoCompleteSrc.Columns.Add(new DataColumn("EmpId"));  
  22.     dtAutoCompleteSrc.Columns.Add(new DataColumn("EmpName"));  
  23.     for (int i = 0; i < 10; i++)  
  24.     {  
  25.         DataRow dr = dtAutoCompleteSrc.NewRow();  
  26.         dr["EmpId"] = i + 1;  
  27.         dr["EmpName"] = "EmpName " + (i + 1).ToString();  
  28.         dtAutoCompleteSrc.Rows.Add(dr);  
  29.     }  
  30.     return dtAutoCompleteSrc;  
  31. }  
The output is given below.

 

However, this would not be a pure auto complete dropdownlist, since we are actually binding all dropdown values at once and the items are not coming on demand.

Another alternative is to implement Bootstrap autocomplete, which is also called "typeahead". This one can be an actual autocomplete, which fetches the data from WebMethod/API based on what the user has requested by typing in TextBox. To implement, you will  need to reference Bootstrap related CSS, scripts and write WebMethod to fetch the data upon the user request as they type. Here is a sample code on a similar scenario. Notice that once you select any element, you will be able to get the ID of the selected item in an HiddenField in an updater function:

  1. <!DOCTYPE html>  
  2.   
  3. <html xmlns="http://www.w3.org/1999/xhtml">  
  4. <head runat="server">  
  5.     <title></title>  
  6.     <script src="Scripts/jquery-1.12.4.min.js"></script>  
  7.     <link href="Content/bootstrap.min.css" rel="stylesheet" />  
  8.     <link href="Content/bootstrap-theme.min.css" rel="stylesheet" />  
  9.     <script src="Scripts/bootstrap.min.js"></script>  
  10.     <script type="text/javascript" src="http://cdn.rawgit.com/bassjobsen/Bootstrap-3-Typeahead/master/bootstrap3-typeahead.min.js"></script>  
  11.     <script type="text/javascript">  
  12.        $(document).ready(function () {  
  13.             $('#txtEmp').typeahead({  
  14.                 hint: true,  
  15.                 highlight: true,  
  16.                 minLength: 1,  
  17.                 source: function (request, response) {  
  18.                     $.ajax({  
  19.                         url: '<%=ResolveUrl("~/WebForm68.aspx/GetEmployeeDataSample") %>',  
  20.                         data: "{ 'SearchParam': '" + request + "'}",  
  21.                         dataType: "json",  
  22.                         type: "POST",  
  23.                         contentType: "application/json; charset=utf-8",  
  24.                         success: function (data) {  
  25.                             items = [];  
  26.                             map = {};  
  27.                             $.each(data.d, function (i, item) {  
  28.                                 var id = item.split('-')[0];  
  29.                                 var name = item.split('-')[1];  
  30.                                 map[name] = { id: id, name: name };  
  31.                                 items.push(name);  
  32.                             });  
  33.                             response(items);  
  34.                             $(".dropdown-menu").css("height", "auto");  
  35.                             $(".dropdown-menu").css("width", "400");  
  36.                         },  
  37.                         error: function (response) {  
  38.                             console.log(response.responseText);  
  39.                         },  
  40.                         failure: function (response) {  
  41.                             console.log(response.responseText);  
  42.                         }  
  43.                     });  
  44.                 },  
  45.                 updater: function (item) {  
  46.                     $('#hdnEmpId').val(map[item].id);  
  47.                     return item;  
  48.                 }  
  49.             });  
  50.         });  
  51.     </script>  
  52. </head>  
  53. <body>  
  54.     <form id="form1" runat="server">  
  55.         <asp:TextBox  
  56.             runat="server"  
  57.             ID="txtEmp"  
  58.             CssClass="form-control"  
  59.             AutoCompleteType="Disabled"  
  60.             ClientIDMode="Static"  
  61.             Width="400" />  
  62.         <asp:HiddenField  
  63.             runat="server"  
  64.             ClientIDMode="Static"  
  65.             ID="hdnEmpId" />  
  66.     </form>  
  67. </body>  
  68. </html>  
Code at the back-end
  1. public partial class WebForm68 : System.Web.UI.Page  
  2. {  
  3.     protected void Page_Load(object sender, EventArgs e)  
  4.     {  
  5.   
  6.     }  
  7.   
  8.     //-- actual  webmethod that will fetch data from database based on what user typed   
  9.     [WebMethod]  
  10.     public static string[] GetEmployeeData(string SearchParam)  
  11.     {  
  12.         List<string> empList = new List<string>();  
  13.         using (SqlConnection conn = new SqlConnection())  
  14.         {  
  15.             conn.ConnectionString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;  
  16.             using (SqlCommand cmd = new SqlCommand())  
  17.             {  
  18.                 cmd.CommandText = "select EmpName, EmpId from EmployeeTable where EmpName like @SearchParam + '%'";  
  19.                 cmd.Parameters.AddWithValue("@SearchParam", SearchParam);  
  20.                 cmd.Connection = conn;  
  21.                 conn.Open();  
  22.                 using (SqlDataReader sdr = cmd.ExecuteReader())  
  23.                 {  
  24.                     while (sdr.Read())  
  25.                         empList.Add(string.Format("{0}-{1}", sdr["EmpName"], sdr["EmpId"]));  
  26.                 }  
  27.                 conn.Close();  
  28.             }  
  29.         }  
  30.         return empList.ToArray();  
  31.     }  
  32.   
  33.     //-- generate sample data for auto complete just to demonstrate  
  34.     [WebMethod]  
  35.     public static string[] GetEmployeeDataSample(string SearchParam)  
  36.     {  
  37.         List<string> empList = new List<string>();  
  38.         for (int i = 0; i < 10; i++)  
  39.         {  
  40.             string data = (i + 1).ToString();  
  41.             data += "-EmpName " + (i + 1).ToString();  
  42.             empList.Add(data);  
  43.         }  
  44.         return empList.Where(x => x.ToLower().Contains(SearchParam)).ToArray();  
  45.     }  
  46. }  

Output is given below.

Reference link: Bootstrap AutoComplete

Another alternative is to use jQuery UI autocomplete: Autocomplete | jQuery UI

Here is a sample code on fetching the data, which is based on the user type.

  1. <!DOCTYPE html>  
  2.   
  3. <html xmlns="http://www.w3.org/1999/xhtml">  
  4. <head runat="server">  
  5.     <title></title>  
  6.     <link href="Content/themes/base/jquery-ui.min.css" rel="stylesheet" />  
  7.     <link href="Content/themes/base/base.css" rel="stylesheet" />  
  8.     <link href="Content/themes/base/autocomplete.css" rel="stylesheet" />  
  9.     <script src="Scripts/jquery-1.12.4.min.js"></script>  
  10.     <script src="Scripts/jquery-ui-1.12.1.min.js"></script>  
  11.     <script type="text/javascript">  
  12.         $(document).ready(function () {  
  13.             InitAutoCompleteEmployee();  
  14.         });  
  15.   
  16.         function InitAutoCompleteEmployee() {  
  17.             $.widget("custom.combobox", {  
  18.                 _create: function () {  
  19.                     this.wrapper = $("<span>")  
  20.                     .addClass("custom-combobox")  
  21.                     .insertAfter(this.element);  
  22.                     this.element.hide();  
  23.                     this._createAutocomplete();  
  24.                     this._createShowAllButton();  
  25.                 },  
  26.                 _createAutocomplete: function () {  
  27.                     var selected = this.element.children(":selected"),  
  28.                     value = selected.val() ? selected.text() : "";  
  29.                     this.input = $("<input>")  
  30.                     .appendTo(this.wrapper)  
  31.                     .val(value)  
  32.                     .attr("title", "")  
  33.                     .attr("style", "width:200px")  
  34.                     .attr("id", "txtEmp")  
  35.                     .addClass("custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left")  
  36.                     .autocomplete({  
  37.                         delay: 0,  
  38.                         //autoFocus: true,  
  39.                         source: function (request, response) {  
  40.                             $.ajax({  
  41.                                 type: "POST",  
  42.                                 url: '<%=ResolveUrl("~/WebForm69.aspx/GetEmployeeDataSample") %>',  
  43.                                 contentType: "application/json; charset=utf-8",  
  44.                                 dataType: "json",  
  45.                                 data: "{ 'SearchParam': '" + $("#txtEmp").val() + "'}",  
  46.                                 success: function (data) {  
  47.                                     var items = [];  
  48.                                     $.each(data.d, function (key, val) {  
  49.                                         var item = {  
  50.                                             label: val.EmpName,  
  51.                                             value: val.EmpId,  
  52.                                             id: val.EmpId,  
  53.                                             costFactor: val.EmpId  
  54.                                         };  
  55.                                         items.push(item);  
  56.                                     });  
  57.                                     source = items;  
  58.                                     response(items);  
  59.   
  60.                                 },  
  61.                                 error: function (xhr) { debugger; }   
  62.                             });  
  63.                         },  
  64.                         select: function (event, ui) {  
  65.                             event.preventDefault();  
  66.                             $("[id$=txtEmp]").val(ui.item.label)  
  67.                         },  
  68.                         focus: function (event, ui) {  
  69.                             event.preventDefault();  
  70.                             $("[id$=txtEmp]").val(ui.item.label);  
  71.                         },  
  72.                     })  
  73.                     .tooltip({  
  74.                         tooltipClass: "ui-state-highlight"  
  75.                     });  
  76.                     this._on(this.input, {  
  77.                         autocompleteselect: function (event, ui) {  
  78.                             this._trigger("select", event, {  
  79.                                 item: ui.item.label  
  80.                             });  
  81.                         },  
  82.                         autocompletechange: "_removeIfInvalid"  
  83.                     });  
  84.                 },  
  85.                 _createShowAllButton: function () {  
  86.                     var input = this.input,  
  87.                     wasOpen = false;  
  88.                     $("<a>")  
  89.                     .attr("tabIndex", -1)  
  90.                     .attr("title", 'Select Employee')  
  91.                     .tooltip()  
  92.                     .appendTo(this.wrapper)  
  93.                     .button({  
  94.                         icons: {  
  95.                             primary: "ui-icon-triangle-1-s"  
  96.                         },  
  97.                         text: false  
  98.                     })  
  99.                     .removeClass("ui-corner-all")  
  100.                     .addClass("custom-combobox-toggle ui-corner-right")  
  101.                     .mousedown(function () {  
  102.                         wasOpen = input.autocomplete("widget").is(":visible");  
  103.                     })  
  104.                     .click(function () {  
  105.                         input.focus();  
  106.                         if (wasOpen) {  
  107.                             return;  
  108.                         }  
  109.                         input.autocomplete("search", "*");  
  110.                     });  
  111.                 },  
  112.                 _source: function (request, response) {  
  113.                     var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");  
  114.                     response(this.element.children("option").map(function () {  
  115.                         var text = $(this).text();  
  116.                         if (this.value && (!request.term || matcher.test(text)))  
  117.                             return {  
  118.                                 label: text,  
  119.                                 value: text,  
  120.                                 option: this  
  121.                             };  
  122.                     }));  
  123.                 },  
  124.                 _removeIfInvalid: function (event, ui) {  
  125.                     if (ui.item) {  
  126.                         return;  
  127.                     }  
  128.                     var value = this.input.val(),  
  129.                     valuevalueLowerCase = value.toLowerCase(),  
  130.                     valid = false;  
  131.                     this.element.children("option").each(function () {  
  132.                         if ($(this).text().toLowerCase() === valueLowerCase) {  
  133.                             this.selected = valid = true;  
  134.                             return false;  
  135.                         }  
  136.                     });  
  137.                     if (valid) {  
  138.                         return;  
  139.                     }  
  140.                     this.input  
  141.                     .val("")  
  142.                     .attr("title", value + 'not found!')  
  143.                     .tooltip("open");  
  144.                     this.element.val("");  
  145.                     $("[id$=hdnEmpId]").val("");  
  146.                     this._delay(function () {  
  147.                         this.input.tooltip("close").attr("title", "");  
  148.                     }, 2500);  
  149.                     this.input.data("ui-autocomplete").term = "";  
  150.                 },  
  151.                 _destroy: function () {  
  152.                     this.wrapper.remove();  
  153.                     this.element.show();  
  154.                 }  
  155.             });  
  156.             $("#ddlEmployee").combobox();  
  157.         }  
  158.     </script>  
  159. </head>  
  160. <body>  
  161.     <form id="form1" runat="server">  
  162.         <asp:DropDownList  
  163.             runat="server"  
  164.             ID="ddlEmployee"  
  165.             ClientIDMode="Static"  
  166.             Width="400" />  
  167.         <asp:HiddenField  
  168.             runat="server"  
  169.             ClientIDMode="Static"  
  170.             ID="hdnEmpId" />  
  171.     </form>  
  172. </body>  
  173. </html>  
Here is WebMethod to bind the data, when the user types any character:
  1. public partial class WebForm69 : System.Web.UI.Page  
  2. {  
  3.     protected void Page_Load(object sender, EventArgs e)  
  4.     {  
  5.     }  
  6.   
  7. //-- actual  webmethod that will fetch data from database based on what user typed  
  8. [WebMethod]  
  9. public static List<Employee> GetEmployeeData(string SearchParam)  
  10. {  
  11.         List<Employee> empList = new List<Employee>();  
  12.     using (SqlConnection conn = new SqlConnection())  
  13.     {  
  14.         conn.ConnectionString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;  
  15.         using (SqlCommand cmd = new SqlCommand())  
  16.         {  
  17.             cmd.CommandText = "select EmpName, EmpId from EmployeeTable where EmpName like @SearchParam + '%'";  
  18.             cmd.Parameters.AddWithValue("@SearchParam", SearchParam);  
  19.             cmd.Connection = conn;  
  20.             conn.Open();  
  21.             using (SqlDataReader sdr = cmd.ExecuteReader())  
  22.             {  
  23.                 while (sdr.Read())  
  24.                         empList.Add(new Employee() { EmpId = Convert.ToInt32(sdr["EmpName"]), EmpName = Convert.ToString(sdr["EmpId"]) });;  
  25.             }  
  26.             conn.Close();  
  27.         }  
  28.     }  
  29.     return empList;  
  30. }  
  31.   
  32.     //-- generate sample data for auto complete just to demonstrate  
  33.     [WebMethod]  
  34.     public static List<Employee> GetEmployeeDataSample(string SearchParam)  
  35.     {  
  36.         List<Employee> empList = new List<Employee>();  
  37.   
  38.         for (int i = 0; i < 10; i++)  
  39.             empList.Add(new Employee() { EmpId = i + 1, EmpName = "EmpName " + (i + 1).ToString() });  
  40.         return empList.Where(record => record.EmpName.ToLower().Contains(SearchParam)).ToList();  
  41.     }  
  42.   
  43.     public class Employee  
  44.     {  
  45.         public int EmpId { getset; }  
  46.   
  47.         public string EmpName { getset; }  
  48.     }  
  49. }  
Output is given below.