Autocomplete dropdown with jQuery UI and MVC

Posted by Joe Wilson on Friday, February 4, 2011 11:03 AM

You know the autocomplete dropdown.  It has become ubiquitous, and customers now expect them in their web apps.  "Can't you just set autocomplete=true or something?"  It's not quite that easy with ASP.NET MVC, but it's pretty simple.

We want to set up a text box on a web page that uses jQuery to call back to a controller action as the user types.  The action method will return a JSON array of values that match what the user has typed so far.  Each time they type and pause for a second, the screen should show the new matching records.

The view

First, we'll work on the view.  Set a reference to jQuery and to jQuery UI.  These are included with new MVC 3 projects (look in the Scripts folder), or you can find a CDN and reference them there.  I've got this in my view's head section:

<head>
    <title>Autocomplete Test </title>
    <script src="<%: Url.Content("~/Scripts/jquery-1.4.4.min.js")%>" type="text/javascript"></script>
    <script src="<%: Url.Content("~/Scripts/jquery-ui.min.js")%>" type="text/javascript"></script>
</head>

Then you need a text box to tie all this too.  The search results will be shown under this text box to give the appearance of a dropdown.  This simple form should do:

<form action="/Search/ProcessTheForm" method="post">
    <input id="searchTerm" name="searchTerm" type="text" />
    <input type="submit" value="Go" />
</form>

Next, you'll need to use the autocomplete function in jQuery UI like this:

<script type="text/javascript">
    $(function () {
        $("#searchTerm").autocomplete({
            source: "/Search/AutocompleteSuggestions",
            minLength: 3,
            select: function (event, ui) {
                if (ui.item) {
                    $("#searchTerm").val(ui.item.value);
                    $("form").submit();
                }
            }
        });
    });
</script>

Here we've got a jQuery selector binding the autocomplete function to the searchTerm input box("#searchTerm").  We then set the URL for the source for the autocomplete suggestions, which in this case, will be our controller (Search) and action method (AutocompleteSuggestions).  Then we set the number of characters the user has to type before we make the first call.  It's set to three here to prevent pulling back meaningless matches from searching too soon.

Finally, we set up the autocomplete function's select event to set the selected value from the dropdown list as the value in the searchTerm input box and submit the form to the Search controller and the ProcessTheForm action method.

Here's the entire view for reference:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

<!DOCTYPE html>
<html>
<head>
    <title>Autocomplete Test</title>
    <script src="<%: Url.Content("~/Scripts/jquery-1.4.4.min.js")%>" type="text/javascript"></script>
    <script src="<%: Url.Content("~/Scripts/jquery-ui.min.js")%>" type="text/javascript"></script>
</head>
<body>
    <form action="/Search/ProcessTheForm" method="post">
        <input id="searchTerm" name="searchTerm" type="text" />
        <input type="submit" value="Go" />
    </form>
    <script type="text/javascript">
        $(function () {
            $("#searchTerm").autocomplete({
                source: "/Search/AutocompleteSuggestions",
                minLength: 3,
                select: function (event, ui) {
                    if (ui.item) {
                        $("#searchTerm").val(ui.item.value);
                        $("form").submit();
                    }
                }
            });
        });
    </script>
</body>
</html>

The controller

Now you need to write something that will return the records that match what the user has entered so far.  This might be a database call with a LIKE searchTerm + "%" (watch out for SQL injection, though) or SOUNDEX or a web service call.  Be sure you limit your returned search results to maybe the top 10 matches so you don't bog things down with too much data moving over the wire.

Next, set up a controller action to invoke this back-end call and JSON up the returned list.  We've already names the controller (Search) and action (AutocompleteSuggestions) in our view.  Something like this should work, where _searchRepository is my repository call that finds matching strings, which are then converted to JSON:

public JsonResult AutocompleteSuggestions(string term)
{
    var suggestions = _searchRepository.GetAutoCompleteSearchSuggestion(term);
    return Json(suggestions, JsonRequestBehavior.AllowGet);
}

Don't forget the JsonRequestBehavior.AllowGet parameter in the Json call.  You won't get anything back from the action method if you leave it off.

Also, the name of the parameter passed into the action method is important.  The jQuery UI autocomplete method will call your source URL with a query string like "?term=foo".  If you set the parameter name to a string named "term", the MVC model binder will grab the value from the query string for you.

The jQuery UI Autocomplete function has several other options and events you can use in your app, and the demos are worth checking out too.

Tags: MVC, jQuery
Categories: Technical

blog comments powered by Disqus

Blog links

  • Subscribe to this blogRSS feed
  • Archive of old posts

Popular posts

  • Autocomplete dropdown with jQuery UI and MVC
  • Handling Exceptions in ASP.NET MVC
  • Don't mock HttpContext
  • Review of Sharp Architecture
  • Evolution of a View in ASP.NET MVC
  • Comparison of Typemock Isolator and Rhino Mocks
  • Building a Windows 8 Live Tile with JavaScript
  • Setting Default Values for Multiple Value Parameters in Reporting Services
  • Buy, Build, or Both?
  • Why bother writing unit tests?

Tag cloud

  • AppHarbor
  • Areas
  • ASP.NET
  • ATDD
  • BDD
  • Castle Windsor
  • Coding Standards
  • Common Service Locator
  • continuous integration
  • Cookies
  • CRM
  • CSS
  • Custom Software
  • Data Annotations
  • DataTables
  • DDD
  • Dell
  • Dependency Injection
  • DTOs
  • ELMAH
  • git
  • GitHub
  • Html Helpers
  • HttpContext
  • IOC
  • iPad
  • iPhone
  • JavaScript
  • jQuery
  • jQuery Mobile
  • JSON
  • Kendo UI
  • Knockout
  • Microsoft Accounting
  • Moq
  • MVC
  • NHibernate
  • NuGet
  • NUnit
  • OData
  • optimizations
  • Patterns
  • POCOs
  • QuickBooks
  • Rails
  • Refactoring
  • Reporting Services
  • REST
  • Rhino Mocks
  • Session
  • Sharp Architecture
  • SOLID
  • SpecFlow
  • SQL Server
  • SSRS
  • TDD
  • TeamCity
  • TempData
  • Typemock
  • unit testing
  • Validation
  • Visual Studio
  • VMWare
  • WatiN
  • WCF
  • Web API
  • Web Essentials
  • Web Forms
  • Windows 7
  • Windows 8
  • WinJS

Archive

  • 2013
    • May (1)
    • April (1)
    • March (1)
    • February (3)
    • January (1)
  • 2012
    • December (1)
    • October (6)
    • September (3)
    • March (1)
  • 2011
    • October (1)
    • August (1)
    • June (3)
    • March (2)
    • February (2)
    • January (4)
  • 2010
    • December (2)
    • October (3)
    • September (1)
    • August (2)
    • July (1)
    • May (1)
    • April (2)
    • March (2)
    • February (3)
    • January (2)
  • 2009
    • November (3)
    • October (2)
    • September (5)
    • August (2)
    • July (3)

Blogroll

  • RSS feed for Dan WahlinDan Wahlin
  • RSS feed for Jimmy BogardJimmy Bogard
  • RSS feed for John PapaJohn Papa
  • RSS feed for Josh TwistJosh Twist
  • RSS feed for Los TechiesLos Techies
  • RSS feed for Phil HaackPhil Haack
  • RSS feed for Scott GuthrieScott Guthrie
  • RSS feed for Scott HanselmanScott Hanselman
  • RSS feed for Steve SandersonSteve Sanderson

Twitter

  • Twitter May 15, 7:20 PM

    At Denver .NET meetup to hear @rlacovara talk about SpecFlow

  • Twitter May 15, 9:26 AM

    @eriklane @extofer @greeleygeek That sounds weird to me, too. Values on the query string, sure, but not JSON.

  • Twitter May 15, 9:24 AM

    @kevinkrueger otherwise, people will not be as forthcoming about areas they hope the team can improve

  • Twitter May 15, 9:24 AM

    @kevinkrueger I think retros are best if they are for the team only, so they can have a frank discussion of how to get better.

  • Twitter May 14, 10:49 AM

    Terrific talk from @zekeli @html5denver last night "Cross domain Pong with window.postMessage" http://t.co/iO0AAlbJ7l http://t.co/5mnf2fZL0p

  • Follow me on TwitterFollow me on Twitter

Recognition

  • INETA Community Champions

Blog license

  • Creative Commons License
    Blog by Volare Systems is licensed under a Creative Commons Attribution 3.0 Unported License.
    Based on a work at http://volaresystems.com/blog/.