jQuery AutoComplete in ASP.NET MVC Framework

Goal:

jQuery AutoComplete in ASP.NET MVC Framework with callback to customize result

 

Platform/Environment:

  • Asp.Net Mvc version 1
  • jQuery 1.3.2
  • Autocomplete - jQuery plugin 1.0.2

 

Quick Solution:


Here I am simply returning a list of account names:

    $('#Name').autocomplete(
        $('#ajaxListMatchingAccountNamesUrl').val(), { delay: 10, minChars: 3, matchSubset: 1, matchContains: 1, cacheLength: 10, autoFill: true, mustMatch: false, selectFirst: true, max: 15 }
    );


ajaxListMatchingAccountNamesUrl - this is a hidden input control in my master page that contains the url that I set as follows so as to allow the Mvc framework to set it dynamically:

<input id="ajaxListMatchingAccountNamesUrl" type="hidden" value="<%=Url.RouteUrl(new {controller = "Account", Action = "GetMatchingAccounts"})%>" />


Here is the C# controller action:

        [AcceptVerbs(HttpVerbs.Get)]
        public string GetMatchingAccounts(string q)
        {
            if (String.IsNullOrEmpty(q))
                return null;

            var sb = new StringBuilder();
            foreach (AccountNameIdDTO dto in _accountRepository.SearchForAccountsStartingWithNameSuffixKey(q))
            {
                sb.AppendLine(dto.Name);
            }
            return sb.ToString();
        }

 

Complex Solution:

A situation where my account names may be the same for different acounts. In this scenario I let the server-side action append the unique ID to the name, surrounded by brackets: My Account Name (23). This way when the user selects the account, I store the name in the textbox and the ID is parsed out and stored in a protected/readonly textbox.

    var $target = $('div#SomeWrapper');
    $target.find("#MasterAccount").autocomplete(
        $('#ajaxListMatchingAccountNamesWithIdSuffixUrl').val(),
        {
            delay:10,
            minChars:3,
            matchSubset:1,
            matchContains:1,
            cacheLength:10,
            autoFill:true,
            mustMatch: false,
            selectFirst : true,
            max: 15,
            formatResult: function(row, i, total) //this is the actual value that will be placed inside the textbox
            {
                //Parse out the ID suffix in brackets and place only the account name itself into the textbox for the name
                $target.find('#MasterAccountId').val(i.substring(i.indexOf('(')+1,i.indexOf(')')));
                return i.substring(0,i.indexOf('('));
            }
        }
    );
   
    $target.find("#MasterAccount").result(SetupCallBackForMasterAccount).next().click(function() {
            $(this).prev().search();
    });
   
    //When the auto complete textbox is empty, delete the key code from the text
    $target.find("#MasterAccount").bind('keyup',function() {
        if ($(this).val() == '')
        {
            $target.find('#MasterAccountId').val('')
        }
    });


//This function parses the matched auto complete value's suffix key (in between parenthesis)
function SetupCallBackForMasterAccount(event, data, formatted) {
    $('#MasterAccountId').val( !data ? " " : formatted.substring(formatted.indexOf('(')+1,formatted.indexOf(')')));
}


Here is the C# code controller action:

        [AcceptVerbs(HttpVerbs.Get)]
        public string GetMatchingAgentsWithIdSuffix(string q)
        {
            if (String.IsNullOrEmpty(q))
                return null;

            var sb = new StringBuilder();
            foreach (AccountNameIdDTO dto in _accountRepository.SearchForAccountsStartingWithNameSuffixKey(q))
            {
                if ((Repository<IAccount>.Get(dto.Id) as Agency) != null)
                    sb.AppendLine(dto.Name + "(" + dto.Id + ")");
            }
            return sb.ToString();
        }

 

Couple of pointers:

  • $target- I declare this variable as I am referencing this container several times and to speed performance let jQuery find it and set the reference only once. You can of course chnage this to anything that fits your needs or simply ignore it and directly target the textbox of interest (MaterAccountId in this example).
  • MasterAccountId - this is the readonly textbox that will contain the value of the unique ID
  • MasterAccount - this is the textbox where the user enters the name of the account
  • minChars:3 - Starts the search after/on three characters
  • selectFirst : true - if the user does not click on the name and simply tabs out will select the first one

Print | posted @ Tuesday, September 8, 2009 9:06 AM

Comments on this entry:

Gravatar # re: jQuery AutoComplete in ASP.NET MVC Framework
by Cameron at 2/17/2010 12:14 AM

Applying to a slightly different problem this code was invaluable. It took me a little time to run correctly because I didn't have my inputs between the wrapper
<div id="AccountMaintenanceWrapper">
</div>
Except for this minor detail it was spot on.
Thanks.
Gravatar # re: jQuery AutoComplete in ASP.NET MVC Framework
by Renso at 2/17/2010 7:50 AM

Thanks for the feedback Cameron. I updated the code example to be less specific, replaced AccountMaintenanceWrapper with "target". I also sped up the performance a bit by removing the string concatenation dto.Name + "(" + dto.Id + ")") and placed it inside my sql call so that sql server takes care of the concatenation. Not sure by how much it sped it up but at least it's not slower :-) If you have any other tips and tricks you are looking for email me at rhollhumer@live.com and I can see if I have sample code I can post in my blog. Thanks again for the feedback.
Post A Comment
Title:
Name:
Email:
Comment:
Verification: