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 that, you suppose to bind the DropDownList just like in similar way done and configure Chosen plugin over the DropDownList control. Here is a sample auto complete DropDownList using Chosen plugin. It also allows you go give selected Item on postbacks on code behind side:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="Content/chosen.min.css" rel="stylesheet" />
    <script src="Scripts/jquery-1.12.4.min.js"></script>
    <script src="Scripts/chosen.jquery.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            InitDropDown();
        })

        function InitDropDown() {
            var config = {
                '.ChosenSelector': { allow_single_deselect: true, search_contains: true, width: "350px" },
            }
            for (var selector in config) {
                $(selector).chosen(config[selector]);
            }
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:DropDownList 
            runat="server" 
            ID="ddlDropDown" 
            DataTextField="EmpName" 
            DataValueField="EmpId"
            CssClass="ChosenSelector"
            data-placeholder="Select Employee"
            AppendDataBoundItems="true">
            <asp:ListItem Text="" Value="-1"></asp:ListItem>
        </asp:DropDownList>
    </form>
</body>
</html>
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        BindDropdown();
    }
}

//-- bind dropdown
private void BindDropdown()
{
    DataTable dtAutoCompleteSrc = GetSampleData();
    ddlDropDown.DataSource = dtAutoCompleteSrc;
    ddlDropDown.DataBind();
}

//-- generate sample data for auto complete
private DataTable GetSampleData()
{
    DataTable dtAutoCompleteSrc = new DataTable();
    dtAutoCompleteSrc.Columns.Add(new DataColumn("EmpId"));
    dtAutoCompleteSrc.Columns.Add(new DataColumn("EmpName"));
    for (int i = 0; i < 10; i++)
    {
        DataRow dr = dtAutoCompleteSrc.NewRow();
        dr["EmpId"] = i + 1;
        dr["EmpName"] = "EmpName " + (i + 1).ToString();
        dtAutoCompleteSrc.Rows.Add(dr);
    }
    return dtAutoCompleteSrc;
}

Output:

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

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

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-1.12.4.min.js"></script>
    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <link href="Content/bootstrap-theme.min.css" rel="stylesheet" />
    <script src="Scripts/bootstrap.min.js"></script>
    <script type="text/javascript" src="http://cdn.rawgit.com/bassjobsen/Bootstrap-3-Typeahead/master/bootstrap3-typeahead.min.js"></script>
    <script type="text/javascript">
       $(document).ready(function () {
            $('#txtEmp').typeahead({
                hint: true,
                highlight: true,
                minLength: 1,
                source: function (request, response) {
                    $.ajax({
                        url: '<%=ResolveUrl("~/WebForm68.aspx/GetEmployeeDataSample") %>',
                        data: "{ 'SearchParam': '" + request + "'}",
                        dataType: "json",
                        type: "POST",
                        contentType: "application/json; charset=utf-8",
                        success: function (data) {
                            items = [];
                            map = {};
                            $.each(data.d, function (i, item) {
                                var id = item.split('-')[0];
                                var name = item.split('-')[1];
                                map[name] = { id: id, name: name };
                                items.push(name);
                            });
                            response(items);
                            $(".dropdown-menu").css("height", "auto");
                            $(".dropdown-menu").css("width", "400");
                        },
                        error: function (response) {
                            console.log(response.responseText);
                        },
                        failure: function (response) {
                            console.log(response.responseText);
                        }
                    });
                },
                updater: function (item) {
                    $('#hdnEmpId').val(map[item].id);
                    return item;
                }
            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:TextBox
            runat="server"
            ID="txtEmp"
            CssClass="form-control"
            AutoCompleteType="Disabled"
            ClientIDMode="Static"
            Width="400" />
        <asp:HiddenField
            runat="server"
            ClientIDMode="Static"
            ID="hdnEmpId" />
    </form>
</body>
</html>
public partial class WebForm68 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    //-- actual  webmethod that will fetch data from database based on what user typed 
    [WebMethod]
    public static string[] GetEmployeeData(string SearchParam)
    {
        List<string> empList = new List<string>();
        using (SqlConnection conn = new SqlConnection())
        {
            conn.ConnectionString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
            using (SqlCommand cmd = new SqlCommand())
            {
                cmd.CommandText = "select EmpName, EmpId from EmployeeTable where EmpName like @SearchParam + '%'";
                cmd.Parameters.AddWithValue("@SearchParam", SearchParam);
                cmd.Connection = conn;
                conn.Open();
                using (SqlDataReader sdr = cmd.ExecuteReader())
                {
                    while (sdr.Read())
                        empList.Add(string.Format("{0}-{1}", sdr["EmpName"], sdr["EmpId"]));
                }
                conn.Close();
            }
        }
        return empList.ToArray();
    }

    //-- generate sample data for auto complete just to demonstrate
    [WebMethod]
    public static string[] GetEmployeeDataSample(string SearchParam)
    {
        List<string> empList = new List<string>();
        for (int i = 0; i < 10; i++)
        {
            string data = (i + 1).ToString();
            data += "-EmpName " + (i + 1).ToString();
            empList.Add(data);
        }
        return empList.Where(x => x.ToLower().Contains(SearchParam)).ToArray();
    }
}

Output:

Reference link: Bootstrap AutoComplete

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

Here is a sample code on fetching data based on user type:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="Content/themes/base/jquery-ui.min.css" rel="stylesheet" />
    <link href="Content/themes/base/base.css" rel="stylesheet" />
    <link href="Content/themes/base/autocomplete.css" rel="stylesheet" />
    <script src="Scripts/jquery-1.12.4.min.js"></script>
    <script src="Scripts/jquery-ui-1.12.1.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            InitAutoCompleteEmployee();
        });

        function InitAutoCompleteEmployee() {
            $.widget("custom.combobox", {
                _create: function () {
                    this.wrapper = $("<span>")
                    .addClass("custom-combobox")
                    .insertAfter(this.element);
                    this.element.hide();
                    this._createAutocomplete();
                    this._createShowAllButton();
                },
                _createAutocomplete: function () {
                    var selected = this.element.children(":selected"),
                    value = selected.val() ? selected.text() : "";
                    this.input = $("<input>")
                    .appendTo(this.wrapper)
                    .val(value)
                    .attr("title", "")
                    .attr("style", "width:200px")
                    .attr("id", "txtEmp")
                    .addClass("custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left")
                    .autocomplete({
                        delay: 0,
                        //autoFocus: true,
                        source: function (request, response) {
                            $.ajax({
                                type: "POST",
                                url: '<%=ResolveUrl("~/WebForm69.aspx/GetEmployeeDataSample") %>',
                                contentType: "application/json; charset=utf-8",
                                dataType: "json",
                                data: "{ 'SearchParam': '" + $("#txtEmp").val() + "'}",
                                success: function (data) {
                                    var items = [];
                                    $.each(data.d, function (key, val) {
                                        var item = {
                                            label: val.EmpName,
                                            value: val.EmpId,
                                            id: val.EmpId,
                                            costFactor: val.EmpId
                                        };
                                        items.push(item);
                                    });
                                    source = items;
                                    response(items);

                                },
                                error: function (xhr) { debugger; } 
                            });
                        },
                        select: function (event, ui) {
                            event.preventDefault();
                            $("[id$=txtEmp]").val(ui.item.label)
                        },
                        focus: function (event, ui) {
                            event.preventDefault();
                            $("[id$=txtEmp]").val(ui.item.label);
                        },
                    })
                    .tooltip({
                        tooltipClass: "ui-state-highlight"
                    });
                    this._on(this.input, {
                        autocompleteselect: function (event, ui) {
                            this._trigger("select", event, {
                                item: ui.item.label
                            });
                        },
                        autocompletechange: "_removeIfInvalid"
                    });
                },
                _createShowAllButton: function () {
                    var input = this.input,
                    wasOpen = false;
                    $("<a>")
                    .attr("tabIndex", -1)
                    .attr("title", 'Select Employee')
                    .tooltip()
                    .appendTo(this.wrapper)
                    .button({
                        icons: {
                            primary: "ui-icon-triangle-1-s"
                        },
                        text: false
                    })
                    .removeClass("ui-corner-all")
                    .addClass("custom-combobox-toggle ui-corner-right")
                    .mousedown(function () {
                        wasOpen = input.autocomplete("widget").is(":visible");
                    })
                    .click(function () {
                        input.focus();
                        if (wasOpen) {
                            return;
                        }
                        input.autocomplete("search", "*");
                    });
                },
                _source: function (request, response) {
                    var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
                    response(this.element.children("option").map(function () {
                        var text = $(this).text();
                        if (this.value && (!request.term || matcher.test(text)))
                            return {
                                label: text,
                                value: text,
                                option: this
                            };
                    }));
                },
                _removeIfInvalid: function (event, ui) {
                    if (ui.item) {
                        return;
                    }
                    var value = this.input.val(),
                    valueLowerCase = value.toLowerCase(),
                    valid = false;
                    this.element.children("option").each(function () {
                        if ($(this).text().toLowerCase() === valueLowerCase) {
                            this.selected = valid = true;
                            return false;
                        }
                    });
                    if (valid) {
                        return;
                    }
                    this.input
                    .val("")
                    .attr("title", value + 'not found!')
                    .tooltip("open");
                    this.element.val("");
                    $("[id$=hdnEmpId]").val("");
                    this._delay(function () {
                        this.input.tooltip("close").attr("title", "");
                    }, 2500);
                    this.input.data("ui-autocomplete").term = "";
                },
                _destroy: function () {
                    this.wrapper.remove();
                    this.element.show();
                }
            });
            $("#ddlEmployee").combobox();
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:DropDownList
            runat="server"
            ID="ddlEmployee"
            ClientIDMode="Static"
            Width="400" />
        <asp:HiddenField
            runat="server"
            ClientIDMode="Static"
            ID="hdnEmpId" />
    </form>
</body>
</html>
public partial class WebForm69 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }

//-- actual  webmethod that will fetch data from database based on what user typed
[WebMethod]
public static List<Employee> GetEmployeeData(string SearchParam)
{
        List<Employee> empList = new List<Employee>();
    using (SqlConnection conn = new SqlConnection())
    {
        conn.ConnectionString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
        using (SqlCommand cmd = new SqlCommand())
        {
            cmd.CommandText = "select EmpName, EmpId from EmployeeTable where EmpName like @SearchParam + '%'";
            cmd.Parameters.AddWithValue("@SearchParam", SearchParam);
            cmd.Connection = conn;
            conn.Open();
            using (SqlDataReader sdr = cmd.ExecuteReader())
            {
                while (sdr.Read())
                        empList.Add(new Employee() { EmpId = Convert.ToInt32(sdr["EmpName"]), EmpName = Convert.ToString(sdr["EmpId"]) });;
            }
            conn.Close();
        }
    }
    return empList;
} //-- generate sample data for auto complete just to demonstrate [WebMethod] public static List<Employee> GetEmployeeDataSample(string SearchParam) { List<Employee> empList = new List<Employee>(); for (int i = 0; i < 10; i++) empList.Add(new Employee() { EmpId = i + 1, EmpName = "EmpName " + (i + 1).ToString() }); return empList.Where(record => record.EmpName.ToLower().Contains(SearchParam)).ToList(); } public class Employee { public int EmpId { get; set; } public string EmpName { get; set; } } }

Output:

Comments

No Comments