JavaScript/jQuery Autocomplete - Getting Started
Drop-down editors allow users to navigate through a list of items, select one or multiple items, and search through the list. To learn how to choose a DevExtreme drop-down editor and for more details about the component's features, refer to the following article: How to Choose a Drop-Down Editor.
jQuery
Angular
Vue
React
Autocomplete is a text box that displays suggestions while a user types.
This tutorial shows how to add an Autocomplete component to the page and configure the component's core settings. As a result, you will create the following UI component:
Each section in this tutorial describes a single configuration step. You can also find the full source code in the following GitHub repository: getting-started-with-autocomplete.
Create Autocomplete and Bind It to Data
To create an Autocomplete component, declare it in the markup and bind the component to a data source.
Use one of the following properties to supply data to the component:
items
Accepts a local data array.dataSource
Accepts a local data array, DataSource object, or DevExtreme data store.
If the data source contains objects, you should specify the valueExpr property. It accepts the name of the data field that uniquely identifies each data object.
The code example below specifies the dataSource as an array and sets valueExpr to Subject
.
jQuery
$(function() { $("#autocomplete").dxAutocomplete({ dataSource: employeesTasks, valueExpr: "Subject" }); });
<html> <head> <!-- ... --> <script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script> <link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/22.2.14/css/dx.light.css"> <script type="text/javascript" src="https://cdn3.devexpress.com/jslib/22.2.14/js/dx.all.js"></script> <script type="text/javascript" src="index.js"></script> <script type="text/javascript" src="data.js"></script> </head> <body> <div id="autocomplete"></div> </body> </html>
const employeesTasks = [ { ID: 1, Assignee: "Mr. John Heart", Subject: "Choose between PPO and HMO Health Plan", disabled: true }, { ID: 2, Assignee: "Mr. John Heart", Subject: "Google AdWords Strategy" }, { ID: 3, Assignee: "Mr. John Heart", Subject: "New Brochures" }, { ID: 4, Assignee: "Mr. John Heart", Subject: "Update NDA Agreement" }, { ID: 5, Assignee: "Mr. John Heart", Subject: "Review Product Recall Report by Engineering Team" }, { ID: 6, Assignee: "Mrs. Olivia Peyton", Subject: "Update Personnel Files" }, { ID: 7, Assignee: "Mrs. Olivia Peyton", Subject: "Review Health Insurance Options Under the Affordable Care Act" }, { ID: 8, Assignee: "Mrs. Olivia Peyton", Subject: "Non-Compete Agreements" }, { ID: 9, Assignee: "Mrs. Olivia Peyton", Subject: "Give Final Approval for Refunds" }, { ID: 10, Assignee: "Mr. Robert Reagan", Subject: "Deliver R&D Plans for 2013" }, { ID: 11, Assignee: "Mr. Robert Reagan", Subject: "Decide on Mobile Devices to Use in the Field" }, { ID: 12, Assignee: "Mr. Robert Reagan", Subject: "Try New Touch-Enabled WinForms Apps" }, { ID: 13, Assignee: "Mr. Robert Reagan", Subject: "Approval on Converting to New HDMI Specification" }, { ID: 14, Assignee: "Ms. Greta Sims", Subject: "Approve Hiring of John Jeffers" }, { ID: 15, Assignee: "Ms. Greta Sims", Subject: "Update Employee Files with New NDA" }, { ID: 16, Assignee: "Ms. Greta Sims", Subject: "Provide New Health Insurance Docs" } ];
Angular
<dx-autocomplete [dataSource]="employeesTasks" valueExpr="Subject" > </dx-autocomplete>
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { DxAutocompleteModule } from 'devextreme-angular'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, DxAutocompleteModule ], providers: [ ], bootstrap: [AppComponent] }) export class AppModule { }
import { Component } from '@angular/core'; import { Service, Task } from './app.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [Service] }) export class AppComponent { employeesTasks: Task[]; constructor(service: Service) { this.employeesTasks = service.getTasks(); } }
import { Injectable } from '@angular/core'; export class Task { ID: number | undefined; Assignee: string | undefined; Subject: string | undefined; disabled?: boolean | undefined; } const employeesTasks: Task[] = [ { ID: 1, Assignee: "Mr. John Heart", Subject: "Choose between PPO and HMO Health Plan", disabled: true }, { ID: 2, Assignee: "Mr. John Heart", Subject: "Google AdWords Strategy" }, { ID: 3, Assignee: "Mr. John Heart", Subject: "New Brochures" }, { ID: 4, Assignee: "Mr. John Heart", Subject: "Update NDA Agreement" }, { ID: 5, Assignee: "Mr. John Heart", Subject: "Review Product Recall Report by Engineering Team" }, { ID: 6, Assignee: "Mrs. Olivia Peyton", Subject: "Update Personnel Files" }, { ID: 7, Assignee: "Mrs. Olivia Peyton", Subject: "Review Health Insurance Options Under the Affordable Care Act" }, { ID: 8, Assignee: "Mrs. Olivia Peyton", Subject: "Non-Compete Agreements" }, { ID: 9, Assignee: "Mrs. Olivia Peyton", Subject: "Give Final Approval for Refunds" }, { ID: 10, Assignee: "Mr. Robert Reagan", Subject: "Deliver R&D Plans for 2013" }, { ID: 11, Assignee: "Mr. Robert Reagan", Subject: "Decide on Mobile Devices to Use in the Field" }, { ID: 12, Assignee: "Mr. Robert Reagan", Subject: "Try New Touch-Enabled WinForms Apps" }, { ID: 13, Assignee: "Mr. Robert Reagan", Subject: "Approval on Converting to New HDMI Specification" }, { ID: 14, Assignee: "Ms. Greta Sims", Subject: "Approve Hiring of John Jeffers" }, { ID: 15, Assignee: "Ms. Greta Sims", Subject: "Update Employee Files with New NDA" }, { ID: 16, Assignee: "Ms. Greta Sims", Subject: "Provide New Health Insurance Docs" } ]; @Injectable() export class Service { getTasks(): Task[] { return employeesTasks; } }
Vue
<template> <DxAutocomplete :data-source="employeesTasks" value-expr="Subject" /> </template> <script> import 'devextreme/dist/css/dx.light.css'; import { DxAutocomplete } from 'devextreme-vue/autocomplete'; import { employeesTasks } from './data.js'; export default { components: { DxAutocomplete }, data() { return { employeesTasks } } } </script>
export const employeesTasks = [ { ID: 1, Assignee: "Mr. John Heart", Subject: "Choose between PPO and HMO Health Plan", disabled: true }, { ID: 2, Assignee: "Mr. John Heart", Subject: "Google AdWords Strategy" }, { ID: 3, Assignee: "Mr. John Heart", Subject: "New Brochures" }, { ID: 4, Assignee: "Mr. John Heart", Subject: "Update NDA Agreement" }, { ID: 5, Assignee: "Mr. John Heart", Subject: "Review Product Recall Report by Engineering Team" }, { ID: 6, Assignee: "Mrs. Olivia Peyton", Subject: "Update Personnel Files" }, { ID: 7, Assignee: "Mrs. Olivia Peyton", Subject: "Review Health Insurance Options Under the Affordable Care Act" }, { ID: 8, Assignee: "Mrs. Olivia Peyton", Subject: "Non-Compete Agreements" }, { ID: 9, Assignee: "Mrs. Olivia Peyton", Subject: "Give Final Approval for Refunds" }, { ID: 10, Assignee: "Mr. Robert Reagan", Subject: "Deliver R&D Plans for 2013" }, { ID: 11, Assignee: "Mr. Robert Reagan", Subject: "Decide on Mobile Devices to Use in the Field" }, { ID: 12, Assignee: "Mr. Robert Reagan", Subject: "Try New Touch-Enabled WinForms Apps" }, { ID: 13, Assignee: "Mr. Robert Reagan", Subject: "Approval on Converting to New HDMI Specification" }, { ID: 14, Assignee: "Ms. Greta Sims", Subject: "Approve Hiring of John Jeffers" }, { ID: 15, Assignee: "Ms. Greta Sims", Subject: "Update Employee Files with New NDA" }, { ID: 16, Assignee: "Ms. Greta Sims", Subject: "Provide New Health Insurance Docs" } ];
React
import 'devextreme/dist/css/dx.light.css'; import { employeesTasks } from './data'; import { Autocomplete } from 'devextreme-react'; function App() { return ( <Autocomplete dataSource={employeesTasks} valueExpr="Subject" /> ); } export default App;
export const employeesTasks = [ { ID: 1, Assignee: "Mr. John Heart", Subject: "Choose between PPO and HMO Health Plan", disabled: true }, { ID: 2, Assignee: "Mr. John Heart", Subject: "Google AdWords Strategy" }, { ID: 3, Assignee: "Mr. John Heart", Subject: "New Brochures" }, { ID: 4, Assignee: "Mr. John Heart", Subject: "Update NDA Agreement" }, { ID: 5, Assignee: "Mr. John Heart", Subject: "Review Product Recall Report by Engineering Team" }, { ID: 6, Assignee: "Mrs. Olivia Peyton", Subject: "Update Personnel Files" }, { ID: 7, Assignee: "Mrs. Olivia Peyton", Subject: "Review Health Insurance Options Under the Affordable Care Act" }, { ID: 8, Assignee: "Mrs. Olivia Peyton", Subject: "Non-Compete Agreements" }, { ID: 9, Assignee: "Mrs. Olivia Peyton", Subject: "Give Final Approval for Refunds" }, { ID: 10, Assignee: "Mr. Robert Reagan", Subject: "Deliver R&D Plans for 2013" }, { ID: 11, Assignee: "Mr. Robert Reagan", Subject: "Decide on Mobile Devices to Use in the Field" }, { ID: 12, Assignee: "Mr. Robert Reagan", Subject: "Try New Touch-Enabled WinForms Apps" }, { ID: 13, Assignee: "Mr. Robert Reagan", Subject: "Approval on Converting to New HDMI Specification" }, { ID: 14, Assignee: "Ms. Greta Sims", Subject: "Approve Hiring of John Jeffers" }, { ID: 15, Assignee: "Ms. Greta Sims", Subject: "Update Employee Files with New NDA" }, { ID: 16, Assignee: "Ms. Greta Sims", Subject: "Provide New Health Insurance Docs" } ];
Group Data
You can group data items in the Autocomplete drop-down list.
If the data source contains ungrouped data items, use the DataSource's group property to specify the data field by which to group.
The component can also work with initially grouped data items. In this case, the data array should contain objects with the key
and items
fields:
let dataSource = [{ key: "Group 1", // Group caption items: [ // Items in Group 1 { /* ... */ }, { /* ... */ } ] }, { key: "Group 2", items: [ { /* ... */ }, { /* ... */ } ] }];
If data objects are grouped but use other field names, implement the map function of the DataSource's group to create key
and items
field mappings.
Regardless of the data source structure, enable the grouped property.
The following code example groups the data source by the Assignee
field and supplies it to the component:
jQuery
$(function() { const dataSource = new DevExpress.data.DataSource({ store: { type: 'array', data: employeesTasks, key: 'ID', }, group: 'Assignee', }); $("#autocomplete").dxAutocomplete({ dataSource, valueExpr: "Subject", grouped: true }); });
Angular
<dx-autocomplete [dataSource]="dataSource" valueExpr="Subject" [grouped]="true" > </dx-autocomplete>
// ... import DataSource from 'devextreme/data/data_source'; import ArrayStore from 'devextreme/data/array_store'; // ... export class AppComponent { employeesTasks: Task[]; dataSource: any; constructor(service: Service) { this.employeesTasks = service.getTasks(); this.dataSource = new DataSource({ store: new ArrayStore({ data: this.employeesTasks, key: "ID" }), group: "Assignee" }); } }
Vue
<template> <DxAutocomplete :data-source="dataSource" value-expr="Subject" :grouped="true" > </DxAutocomplete> </template> <script> // ... import DataSource from 'devextreme/data/data_source'; export default { components: { DxAutocomplete }, data() { return { dataSource: new DataSource({ store: { type: 'array', data: employeesTasks, key: 'ID', }, group: 'Assignee', }), } } } </script>
React
// ... import DataSource from 'devextreme/data/data_source'; function App() { const dataSource = new DataSource({ store: { type: 'array', data: employeesTasks, key: 'ID', }, group: 'Assignee', }); return ( <Autocomplete dataSource={dataSource} valueExpr="Subject" grouped={true} > </Autocomplete> ); } export default App;
Configure Search Settings
Usually, the data field that supplies Autocomplete with suggestions (valueExpr) is the same data field where users search text. If you use two different fields, do the following:
- Assign the field that supplies Autocomplete with suggestions to the valueExpr property.
- Assign the field for search queries to the searchExpr property.
Note that searchExpr also accepts arrays if you want to search by multiple fields.
The Autocomplete component can supply suggestions in two different modes: 'contains' (default) and 'startswith'. You can use the searchMode property to change the mode.
When a user types the first character, Autocomplete displays suggestions. To increase the minimum number of typed characters, use the minSearchLength property. To limit the maximum number of characters that a user can type in, use the maxLength property. You can also specify the time interval before the Autocomplete component displays a suggestion after user input. Assign this time interval in milliseconds to the searchTimeout property.
The following code example specifies the searchTimeout and maxLength properties:
jQuery
$(function() { // ... $("#autocomplete").dxAutocomplete({ // ... searchTimeout: 300, maxLength: 20 }); });
Angular
<dx-autocomplete ... [searchTimeout]="300" [maxLength]="20" > </dx-autocomplete>
Vue
<template> <DxAutocomplete ... :search-timeout="300" :max-length="20" > </DxAutocomplete> </template> <script> // ... </script>
React
// ... function App() { // ... return ( <Autocomplete ... searchTimeout={300} maxLength={20} > </Autocomplete> ); } export default App;
Customize Field Appearance
Specify the height and width properties to change the size of the Autocomplete text field. If you want to resize the drop-down list, use the dropDownOptions object.
To specify one of the predefined styles for the Autocomplete text field, use the stylingMode property.
Use the placeholder property to give users a hint about what they should type in the Autocomplete text field. You can also use the label property for this purpose. If you specify the label property, set the labelMode property to one of the following values:
"static"
The component displays the label above the input field."floating"
The component uses the label as a placeholder, but when the editor gets focus, the label moves to the position above the input field."hidden"
The label is hidden.
In this tutorial, the component also uses the label as a placeholder, because the labelMode property is set to "floating".
Additionally, Autocomplete can display the following buttons:
A clear button
Specify the showClearButton property. This tutorial uses this button.A drop-down button
Specify the showDropDownButton property. You can use the dropDownButtonTemplate to customize the button appearance.Custom buttons
Implement the buttons array.
jQuery
$(function() { // ... $("#autocomplete").dxAutocomplete({ // ... label: "Search for a task", labelMode: "floating", showClearButton: true }); });
Angular
<dx-autocomplete ... label="Search for a task" labelMode="floating" [showClearButton]="true" > </dx-autocomplete>
Vue
<template> <DxAutocomplete ... label="Search for a task" label-mode="floating" :show-clear-button="true" > </DxAutocomplete> </template> <script> // ... </script>
React
// ... function App() { // ... return ( <Autocomplete ... label="Search for a task" labelMode="floating" showClearButton={true} > </Autocomplete> ); } export default App;
Customize Item Appearance
jQuery
To customize the appearance of all Autocomplete suggestions, define an item template.
If your data is grouped, you may want to customize the group headings. Define a group template for that purpose.
You can also enable wrapItemText to wrap the text if the item's text exceeds the width of the drop-down list.
$(function() { // ... $("#autocomplete").dxAutocomplete({ // ... groupTemplate ({ key }) { return "Assigned to " + key; }, itemTemplate ({ Subject }, index) { return index + 1 + '. ' + Subject; }, wrapItemText: true }); });
Angular
To customize the appearance of all Autocomplete suggestions, define an item template. To customize an individual suggestion, use custom templates property.
If your data is grouped, you may want to customize the group headings. Define a group template for that purpose.
You can also enable wrapItemText to wrap the text if the item's text exceeds the width of the drop-down list.
<dx-autocomplete ... groupTemplate="group" itemTemplate="item" [wrapItemText]="true" > <div *dxTemplate="let data of 'group'"> {{ "Assigned to " + data.key }} </div> <div *dxTemplate="let item of 'item', let index=index"> {{ index + 1 + ". " + item.Subject }} </div> </dx-autocomplete>
Vue
To customize the appearance of all Autocomplete suggestions, define an item template. To customize an individual suggestion, use custom templates property.
If your data is grouped, you may want to customize the group headings. Define a group template for that purpose.
You can also enable wrapItemText to wrap the text if the item's text exceeds the width of the drop-down list.
<template> <DxAutocomplete ... :wrap-item-text="true" group-template="group" item-template="item" > <template #group="{data}"> {{ "Assigned to " + data.key }} </template> <template #item="{data, index}"> {{ index + 1 + ". " + data.Subject }} </template> </DxAutocomplete> </template> <script> // ... </script>
React
To customize the appearance of all Autocomplete suggestions, implement the itemRender or itemComponent function. To customize an individual suggestion, specify the render or component property.
If your data is grouped, you may want to customize the group headings. Implement the groupRender or groupComponent function for that purpose.
You can also enable wrapItemText to wrap the text if the item's text exceeds the width of the drop-down list.
// ... const groupRender = (e) => { return "Assigned to " + e.key; } const itemRender = (e, index) => { return index + 1 + ". " + e.Subject; } function App() { // ... return ( <Autocomplete ... groupRender={groupRender} itemRender={itemRender} wrapItemText={true} /> ); } export default App;
Handle Value Change
Implement the onValueChanged handler to perform an action when a user selects an item or types in the Autocomplete text field. In the code example below, this function logs previous and new values in the console.
jQuery
$(function() { // ... $("#autocomplete").dxAutocomplete({ // ... onValueChanged: function(e) { console.log(e.value); console.log(e.previousValue); }, }); });
Angular
<dx-autocomplete ... (onValueChanged)="onValueChanged($event)"> </dx-autocomplete>
// ... export class AppComponent { // ... onValueChanged(e) { console.log(e.previousValue); console.log(e.value); } }
Vue
<template> <DxAutocomplete ... @value-changed="onValueChanged" /> </template> <script> export default { // ... methods: { onValueChanged(e) { console.log(e.previousValue); console.log(e.value); } } } </script>
React
// ... import React, { useCallback } from 'react'; function App() { // ... const onValueChanged = useCallback((e) => { console.log(e.previousValue); console.log(e.value); }, []); return ( <Autocomplete ... onValueChanged={onValueChanged} /> ); } export default App;
If you have technical questions, please create a support ticket in the DevExpress Support Center.