jQuery UI Helpers / Autocomplete

Data Source

Every autocomplete needs a data source, so all overloads of Autocomplete and AutocompleteFor accept a source parameter. The type of this parameter is string but it can mean three different things. If it contains at least one / character then it is treated as a URL otherwise as a name of a JavaScript object (function or array).

  • If it is a URL, the server must return JSON data: an array of strings or an array of objects with a label or value property.
  • The JavaScript array must contain strings or objects with a label or value property.
  • The JavaScript function must call a specified callback function and give it an array of strings or an array of objects with a label or value property.

You can find more information in the jQuery UI documentation.

The data you give to the autocomplete must be an array of strings or an array of objects with a name OR value property. If the objects you give to the autocomplete have both name and value properties then the autocomplete will display the name in the suggestion list and it will put the selected value into the input element (it will be displayed there after the list is closed). For a more sophisticated solution see the Submitting the id section.

Let's see an example for all source types.

First we need an action method on a controller that returns some data - this will be the remote data source specified by its URL. This example searches a list of cities and returns the names of the first ten which start with the specified term. The parameter name is important here - it must be term.

        public ActionResult SearchCityName(string term)
        {
            var result = CityList
                .Where(c => c.Name.StartsWith(term, StringComparison.CurrentCultureIgnoreCase))
                .Take(10)
                .Select(c => c.Name)
                .ToList();
            return Json(result, JsonRequestBehavior.AllowGet);
        }

The next two data sources are defined in JavaScript: an array with color names, and a function which searches this array (you could execute an AJAX call to get the data from a remote source or create it any other way you want).

var colors = ['White', 'Yellow', 'Fuchsia', 'Red', 'Silver', 'Gray', 'Olive', 'Purple', 'Maroon', 'Aqua', 'Lime', 'Teal', 'Green', 'Blue', 'Navy', 'Black'];

function searchColor(request, callback) {
    result = [];
    for (var i = 0; i < colors.length; i++) {
        if (colors[i].toLowerCase().indexOf(request.term.toLowerCase()) === 0) {
            result.push(colors[i]);
        }
    }
    callback(result);
}

After defining the data sources you can create the autocomplete widgets like this.

<div class="editor-field">
<label for="city1">City 1 </label>
@Html.JQueryUI().Autocomplete("city1", Url.Action("SearchCityName"))
</div>
<div class="editor-field">
<label for="color1">Color 1 </label>
@Html.JQueryUI().Autocomplete("color1", "colors")
</div>
<div class="editor-field">
<label for="color2">Color 2 </label>
@Html.JQueryUI().Autocomplete("color2", "searchColor")
</div>

The first one gets a URL as its source, the second one the name of the array and the third one the name of the function. This is the result (try typing in the boxes):

Submitting the id

The autocomplete widgets in the previous example submit the selected string when you click the submit button. But sometimes on the server you are interested in the id (value) of the selected item while still displaying the name (label) on the client. To support this scenario both Autocomplete and AutocompleteFor methods have overloads that take autcompleteId and autocompleteText parameters. These helpers generate an additional hidden input and use it to store the selected value. The autocompleteText is optinal - you can use it to display the name of the initially selected item if there is any.

When using these methods you must give the autocomplete an array of objects which have both label and value properties.

An example should make all this very clear.

Here is a new action method which searches the cities. Notice that now it returns objects with label and value properties.

        public ActionResult SearchCity(string term)
        {
            var result = CityList
                .Where(c => c.Name.StartsWith(term, StringComparison.CurrentCultureIgnoreCase))
                .Take(10)
                .Select(c => new { label = c.Name, value = c.CityId })
                .ToList();
            return Json(result, JsonRequestBehavior.AllowGet);
        }

To use this action your view might look like this.

@model Address
<div class="editor-field">
<label for="CityId">City</label>
@Html.JQueryUI().AutocompleteFor(m => m.CityId, Url.Action("SearchCity"), "CityName", null)
</div>

The generated HTML:

<div class="editor-field">
<label for="CityId">City</label>
<input data-jqui-acomp-hiddenvalue="CityId" data-jqui-acomp-source="/Docmo/Autocomplete/SearchCity" data-jqui-type="autocomplete" id="CityName" name="CityName" type="text" value="" /><input data-val="true" data-val-number="The field CityId must be a number." id="CityId" name="CityId" type="hidden" value="" />
</div>

And finally the running example.

HTML Helpers

Fluent Configuration API