Ajax Autocomplete for jQuery

May 22, 2026 · View on GitHub

Adds autocomplete / autosuggest dropdowns to text input fields.

The only runtime dependency is jQuery 3.0 or newer. TypeScript types are bundled. The UMD bundle (dist/jquery.autocomplete.js) is ~13 KB minified; an ESM build (dist/jquery.autocomplete.esm.js) is also published for modern bundlers.

Install

npm install devbridge-autocomplete

Or load via a <script> tag — the UMD bundle registers $.fn.autocomplete (and $.fn.devbridgeAutocomplete) on the global jQuery.

Upgrading from 1.x

Version 2.0 drops support for jQuery 1.x / 2.x and IE-era browsers. The plugin API and option names are unchanged — every existing call site continues to work — but the peer dependency is now jquery >=3.0 and the build targets evergreen browsers (ES2020). If you cannot upgrade jQuery, stay on the 1.5.x release line.

API

$(selector).autocomplete(options);

options is an object literal. All recognized fields are listed in the tables below.

General settings (local and Ajax)

SettingDefaultDescription
minChars1Minimum characters typed before suggestions are fetched
delimiteroptionalstring or RegExp that splits the input value; the last segment becomes the query. Useful for comma-separated value lists
noCachefalseIf true, suggestion results are not cached
preventBadQueriestrueIf true, suppresses future Ajax requests for any query that starts with a prefix that previously returned no results. E.g. once Jam returns nothing, Jamai will not fire
triggerSelectOnValidInputtrueIf true, onSelect fires automatically when the input exactly matches a suggestion
autoSelectFirstfalseIf true, the first item is selected when suggestions appear
preserveInputfalseIf true, the input value does not change while navigating suggestions with arrow keys
tabDisabledfalseIf true, pressing Tab keeps the cursor in the input field instead of selecting the highlighted suggestion
showNoSuggestionNoticefalseIf true, displays a label when no suggestions match
noSuggestionNotice"No results"Text, HTML string, Element, or jQuery object used as the no-match label
groupByoptionalProperty on suggestion.data to group results by
formatResultoptionalfunction (suggestion, currentValue) — custom HTML for a single suggestion entry
formatGroupoptionalfunction (suggestion, category) — custom HTML for a group header
beforeRenderoptionalfunction (container, suggestions) — called before the dropdown is shown; mutate the DOM here if needed
onInvalidateSelectionoptionalfunction () — fires when the input changes after a selection was made. this is the input element
maxHeight300Maximum dropdown height in pixels
width"auto"Dropdown width. Number (px), "auto" (matches the input), or "flex" (grows to widest suggestion)
zIndex9999z-index of the dropdown container
orientation"bottom""top", "bottom", or "auto". "auto" picks the side with more room
appendTodocument.bodyjQuery object, selector, or HTMLElement. The target needs position: absolute or position: relative
forceFixPositionfalseAuto-positioning only runs when the dropdown is appended to <body>. Set this to true to force positioning in other parents
containerClass"autocomplete-suggestions"CSS class on the dropdown container. Override if you need a different style hook

Event callbacks (local and Ajax)

CallbackSignatureDescription
onSearchStartfunction (params)Fires before each lookup. Return false to cancel. this is the input element
onSearchCompletefunction (query, suggestions)Fires after each lookup resolves. this is the input element
onSearchErrorfunction (query, jqXHR, textStatus, errorThrown)Fires if the Ajax request fails. this is the input element
onSelectfunction (suggestion)Fires when the user picks a suggestion. this is the input element
onHintfunction (hint)Fires when the inline hint changes. this is the input element
onHidefunction (container)Fires before the dropdown is hidden
transformResultfunction (response, originalQuery)Normalizes the raw server response into { suggestions: [...] }. Default: JSON.parse on a string response

Local-only settings

SettingDefaultDescription
lookupoptionalEither an array of suggestions or a callback function (query, done). Arrays may be strings or { value, data } objects
lookupFilteroptionalfunction (suggestion, query, queryLowerCase) — filter predicate. Default is a case-insensitive substring match
lookupLimitunlimitedMaximum number of local matches to display

A suggestion is an object of the form { value: string, data: any }. data is passed through untouched to formatResult, onSelect, and the grouping key resolver.

Ajax-only settings

SettingDefaultDescription
serviceUrlrequired for AjaxA URL string, or function (query) returning a URL string
type"GET"HTTP method
dataType"text""text", "json", or "jsonp". jsonp is recognized by jQuery's Ajax layer
paramName"query"Name of the request parameter holding the query
paramsoptionalExtra parameters merged into every request
ignoreParamsfalseIf true, suppresses the query-string data payload. Useful when serviceUrl is a callback that builds the entire URL itself
deferRequestBy0Milliseconds to wait before firing the request, so fast typists don't trigger one per keystroke
ajaxSettingsoptionalExtra jQuery Ajax settings merged into the request

Default options

Defaults are accessible (and writable) at $.Autocomplete.defaults.

Instance methods

MethodDescription
setOptions(options)Updates any option(s) at any time
clear()Clears the suggestion cache and the current suggestions
clearCache()Clears only the suggestion cache
disable()Deactivates autocomplete
enable()Reactivates autocomplete after disable()
hide()Hides the dropdown
dispose()Destroys the instance, detaches all event handlers, and removes the dropdown container

There are two ways to call a method. Pass the method name as a string, followed by any arguments:

$('#autocomplete').autocomplete('disable');
$('#autocomplete').autocomplete('setOptions', options);

Or grab the Autocomplete instance by calling autocomplete() with no arguments, then invoke the method on it:

$('#autocomplete').autocomplete().disable();
$('#autocomplete').autocomplete().setOptions(options);

Usage

HTML:

<input type="text" name="country" id="autocomplete" />

Ajax lookup:

$('#autocomplete').autocomplete({
    serviceUrl: '/autocomplete/countries',
    onSelect: function (suggestion) {
        console.log(`Picked: ${suggestion.value}, ${suggestion.data}`);
    },
});

Local lookup (no Ajax):

const countries = [
    { value: 'Andorra', data: 'AD' },
    // ...
    { value: 'Zimbabwe', data: 'ZZ' },
];

$('#autocomplete').autocomplete({
    lookup: countries,
    onSelect: function (suggestion) {
        console.log(`Picked: ${suggestion.value}, ${suggestion.data}`);
    },
});

Custom lookup function — do whatever you want, then call done with the result:

$('#autocomplete').autocomplete({
    lookup: function (query, done) {
        done({
            suggestions: [
                { value: 'United Arab Emirates', data: 'AE' },
                { value: 'United Kingdom', data: 'UK' },
                { value: 'United States', data: 'US' },
            ],
        });
    },
    onSelect: function (suggestion) {
        console.log(`Picked: ${suggestion.value}, ${suggestion.data}`);
    },
});

Styling

The generated dropdown markup looks like this — style any of the classes to taste:

<div class="autocomplete-suggestions">
    <div class="autocomplete-group"><strong>NHL</strong></div>
    <div class="autocomplete-suggestion autocomplete-selected">...</div>
    <div class="autocomplete-suggestion">...</div>
    <div class="autocomplete-suggestion">...</div>
</div>

Minimal CSS to get started:

.autocomplete-suggestions { border: 1px solid #999; background: #fff; overflow: auto; }
.autocomplete-suggestion  { padding: 2px 5px; white-space: nowrap; overflow: hidden; cursor: pointer; }
.autocomplete-selected    { background: #f0f0f0; }
.autocomplete-suggestions strong { font-weight: normal; color: #3399ff; }
.autocomplete-group { padding: 2px 5px; }
.autocomplete-group strong { display: block; border-bottom: 1px solid #000; }

cursor: pointer on .autocomplete-suggestion is required for tap-to-select to fire on mobile Safari — see issue #542.

Response format

The server must respond with JSON in this shape:

{
    "suggestions": [
        { "value": "United Arab Emirates", "data": "AE" },
        { "value": "United Kingdom", "data": "UK" },
        { "value": "United States", "data": "US" }
    ]
}

data may be any value or object — it is passed unchanged to formatResult, onSelect, and the grouping key resolver. If you have no data, a plain string array is also accepted:

{ "suggestions": ["United Arab Emirates", "United Kingdom", "United States"] }

The optional query field on the response was required up to version 1.2.5; newer versions ignore it.

Non-standard request / response format

If your service expects a differently named query parameter or returns a non-standard payload, use paramName and transformResult:

$('#autocomplete').autocomplete({
    paramName: 'searchString',
    transformResult: function (response) {
        return {
            suggestions: response.myData.map((item) => ({
                value: item.valueField,
                data: item.dataField,
            })),
        };
    },
});

Grouping results

Set groupBy to a property name on suggestion.data to render group headers. For example, groupBy: 'category' with this data:

[
    { value: 'Chicago Blackhawks', data: { category: 'NHL' } },
    { value: 'Chicago Bulls', data: { category: 'NBA' } },
];

renders two groups, NHL and NBA.

Known issues

jQuery UI also defines a plugin named autocomplete. When both are loaded, this plugin yields and registers only $.fn.devbridgeAutocomplete, so use the alias:

$('.autocomplete').devbridgeAutocomplete({ ... });

Security

To report a vulnerability, please do not open a public GitHub issue. Use GitHub's Private Vulnerability Reporting form on this repository — it routes the report directly to the maintainers. Full policy and supported-version table: SECURITY.md.

License

Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license. The copyright and permission notices must be included with any copy or substantial portion of the software.

Authors

Tomas Kirda / @tkirda