Introduction
I have looked at a lot of of the AJAX autocomplete options available, but most of them fall short in one way or another.
Your options were either:
- Load a small amount of data on the page and let
JavaScript filter it (the user can still scroll through the data).
- Load large amounts of data by searching through
AJAX queries (but the user cannot scroll through the data).
You could not do both...until now. Try out a live demo of the solution on my website.
This is made possible by the Select2
jQuery autocomplete plugin. Although it has very good documentation I still had some trouble getting it up and running in a .NET MVC environment. To make this a little easier to get started with (and to encourage more people to use this fantastic plugin), I decided to put together a sample MVC project that uses this solution.
Background
This article assumes a familiarity with jQuery and with .NET MVC. If you are accessing someone else's
JSON service, you just need the jQuery experience, but if you need to create the front and back end it would help to be familiar with .NET MVC as well.
This project was built using Visual Studio 2012 Express. You can download Visual Studio Express for free if you do not have it.
Select2 settings and code examples can be found on their site.
The demo project requires NuGet to be installed, since it re-downloads the required dependencies for the project to run.
The code is also available for download on GitHub.
Using the code
JavaScript Includes
To get started, download the latest version of
jQuery as well as the
CSS and JavaScript for Select2. Both of these can also be downloaded via NuGet inside Visual Studio.
<link href="~/Content/css/select2.css" type="text/css" rel="stylesheet" />
<script src="~/Scripts/jquery-2.0.3.js"></script>
<script src="~/Scripts/select2.js"></script>
To get this working on the front end, you will need:
- A textbox with an id to identify it. This is the area on the page where Select2 will load the results of your json query.
- The
URL of your JSON service. This is where we will look for more data for the dropdown.
- To configure the settings to determine how you want this to work (delay before running the query, how many results to return, etc.
The core of the
JavaScript is here:
var attendeeUrl = '@Url.Action("GetAttendees", "Home")';
var pageSize = 20;
$('#attendee').select2(
{
placeholder: 'Enter name',
minimumInputLength: 0,
allowClear: true,
ajax: {
quietMillis: 150,
url: attendeeUrl,
dataType: 'jsonp',
data: function (term, page) {
return {
pageSize: pageSize,
pageNum: page,
searchTerm: term
};
},
results: function (data, page) {
var more = (page * pageSize) < data.Total;
return { results: data.Results, more: more };
}
}
});
And our html textbox where we will store the data looks like this:
<input id="attendee" name="AttendeeId" type="text" value="" />
That's really all that is needed on the front end to get this going. Things get a little more involved if you have to setup the backend as well, but it's nothing we can't handle.
Setting Up the JSON Service
We need to send the data from our backend to Select2 in a certain format. Basically we need to send an id and text value for each result returned. We also need to return the total count of all the results that are returned.
This is so when we start scrolling through the data Select2 knows if it needs to keep requesting more data or if we are at the end of our results.
So the classes we'll create to hold our results look like this:
public class Select2PagedResult
{
public int Total { get; set; }
public List<Select2Result> Results { get; set; }
}
public class Select2Result
{
public string id { get; set; }
public string text { get; set; }
}
Our method that returns the JSON is going to go to our data store, get any attendees that match the search term typed into the dropdownlist, and is then going to convert that data into the
Select2PagedResult
class, which it will then send back to the browser as our
JSON result.
[HttpGet]
public ActionResult GetAttendees(string searchTerm, int pageSize, int pageNum)
{
AttendeeRepository ar = new AttendeeRepository();
List<Attendee> attendees = ar.GetAttendees(searchTerm, pageSize, pageNum);
int attendeeCount = ar.GetAttendeesCount(searchTerm, pageSize, pageNum);
Select2PagedResult pagedAttendees = AttendeesToSelect2Format(attendees, attendeeCount);
return new JsonpResult
{
Data = pagedAttendees,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
All the code to get test data from our data store, search through the first and last names in the last, and convert the results to a Select2PagedResult class is included in the sample project.
Performance
Is it worth going through all this effort? If you have small lists of data, probably not. For lists with 100 items or less in them, the default
JavaScript filtering in Select2 is fast enough and is much easier to setup (just a few lines of code).
In my demo example, the code is filtering a list with 1000 attendees quickly and easily, since all the heavy lifting is done by the server and the
JavaScript only has to display 20 results at a time. In cases like this, setting up Select2 with a remote data source will be worth the time you put in.
History