Skip to main content

Autocomplete

Typeahead search component with a dropdown result list. Extends GuiCommons and is used for searching records with server-side or client-side filtering. The component provides a text input, a search button, a clear button, and a dropdown menu that displays matching results as the user types.

Import: @io-oidis-usercontrols/.../Autocomplete.js (also exports AutocompleteItem, IAutocompleteHandlers, IAutocompleteQuery, IAutocompleteLocalization)

Localization requires subclassing

The localization property is protected and embedded into HTML at construction time via innerHtml(). You cannot set it from the controller after creation — always use a subclass with constructor overrides. See Localization below.

Basic Usage​

Declare the control in the panel, bind it in the template, and configure handlers in the controller.

// Panel
public readonly userSearch : Autocomplete;

// Constructor
this.userSearch = new Autocomplete();
<!-- innerHtml() -->
<div data-oidis-bind="${this.userSearch}"></div>
// Controller — bind in beforeLoad() or resolver()
$instance.userSearch.Bind({
fetchHandler: async ($query : any) : Promise<IAutocompleteData[]> => {
return (await this.client.SearchUsers($query)).data;
},
onSearch: async ($query : IAutocompleteQuery) : Promise<void> => {
this.selectedUser = null;
await this.refreshResults($query);
}
});
Autocomplete requires constructor initialization

Unlike simple controls (TextField, Button) that use = undefined, Autocomplete must be created with new Autocomplete() in the panel constructor because it is a composite component that initializes internal sub-components (searchField, search, clear, etc.) during construction.

Bind Handlers​

The Bind() method accepts an IAutocompleteHandlers object that configures the component behavior.

HandlerSignaturePurpose
fetchHandler($query : any) => Promise<IAutocompleteData[]>Fetch results from server. Receives the query (text by default, or custom object via setSearchToQueryFormatter). Required.
dataToItemMapper($data : IAutocompleteData, $item : AutocompleteItem) => Promise<void>Map each result to an AutocompleteItem. Default: sets Data, Text, and Value from the IAutocompleteData fields.
itemCreateFormatter($item : AutocompleteItem, $index : number) => Promise<void>Custom setup for each dropdown item. Default: binds click to select the item, set the value, and close the dropdown.
onSearch($query : IAutocompleteQuery) => Promise<void>Fired when the search button is clicked. Receives {query, id}. Required.
onSelect($item : AutocompleteItem) => voidFired when keyboard navigation highlights an item. Default: sets Active(true) and scrolls the item into view.
onClear() => Promise<void>Fired when the clear button is clicked (after the component resets). Default: calls onSearch(null) when ReloadOnClear is enabled.
Only override what you need

The default dataToItemMapper and itemCreateFormatter handle standard use cases. Override them only when you need custom item rendering (icons, badges, multi-line content) or non-standard selection behavior.

IAutocompleteData​

The data structure returned by fetchHandler and used internally by the dropdown items.

interface IAutocompleteData {
text : string; // Display text for the item
value? : any; // Associated data object (typically the record)
}

IAutocompleteQuery​

The query object passed to onSearch and used internally when SearchOnSelect triggers a search after item selection.

interface IAutocompleteQuery {
query? : string; // Search text from the input field
id? : string; // Associated identifier (from selected item's data)
}

Configuration​

Getter/setter properties for controlling component behavior. Set these after construction, before or after Bind().

PropertyTypeDefaultPurpose
Triggernumber3Minimum characters before triggering fetchHandler. Must be greater than 0.
ReloadOnClearbooleanfalseWhen cleared, trigger onSearch(null) via the onClear handler.
HintOnFocusbooleanfalseWhen the search field receives focus, trigger a fetch immediately.
SearchOnSelectbooleanfalseWhen an item is selected from the dropdown, trigger onSearch with the current query and selected item id.
SearchButtonVisiblebooleantrueShow or hide the search button. Note: hiding is blocked when SearchOnSelect is false (the search button remains as the only way to trigger search).
// Example: configure for immediate search on focus with low trigger threshold
$instance.userSearch.Trigger = 1;
$instance.userSearch.HintOnFocus = true;
$instance.userSearch.SearchOnSelect = true;
$instance.userSearch.SearchButtonVisible = false;

Value and Data​

Method / PropertyPurpose
Value (get/set)Get or set the search text. The setter strips HTML tags for safety.
Data($value?)Get or set the associated data object (typically the selected record). Delegates to the internal autocomplete component.
Clear()Full reset: clears the input value, removes all result items, clears associated data, re-enables text editing, and hides the clear button.
Show()Opens the dropdown using the Bootstrap Dropdown API and focuses the search field.
Hide()Closes the dropdown.
// Read current search text
const searchText : string = $instance.userSearch.Value;

// Set value programmatically
$instance.userSearch.Value = "John Doe";

// Read associated data (set when an item is selected)
const selectedUser : User = <User>$instance.userSearch.Data();

// Full reset
$instance.userSearch.Clear();

Custom Formatters​

Two protected methods control how the search text is transformed into a query and how results are transformed into display text. Override them via public setters.

Search-to-Query Formatter​

Transforms the raw search text into a query object passed to fetchHandler. Default: passes the text string as-is.

$instance.userSearch.setSearchToQueryFormatter(($value : string) : any => {
return { query: $value, type: "user" };
});

Result-to-Value Formatter​

Transforms an IAutocompleteData result into the display text shown in the input field when an item is selected. Default: returns $data.text.

$instance.userSearch.setResultToValueFormatter(($value : IAutocompleteData) : string => {
return `${$value.value.FirstName} ${$value.value.LastName}`;
});

Keyboard Navigation​

The component supports full keyboard navigation when the dropdown is open:

KeyAction
Arrow DownMove highlight to the next item (wraps to first)
Arrow UpMove highlight to the previous item (stops at first)
EnterSelect the highlighted item, or re-fetch if data is already set and no item is highlighted
EscapeClose the dropdown and clear the selection state

Navigation state is tracked via an internal currentIndex. The onSelect handler is called for each highlighted item (default: sets Active(true) and scrolls the dropdown).

Localization​

The localization property controls the search button text and the input placeholder. Since it is embedded into HTML during innerHtml(), it must be set in the constructor via subclassing.

interface IAutocompleteLocalization {
searchBtnText : string; // Search button label (default: "Search")
placeholderHint : string; // Input placeholder (default: "Looking for something?")
}
export class MyAutocomplete extends Autocomplete {
constructor() {
super();
this.localization = {
searchBtnText : "Find",
placeholderHint : "Type to search..."
};
}
}
Protected properties require subclassing

localization is protected and embedded into HTML at construction time via innerHtml(). You cannot set it from the controller after the component is created — the HTML is already rendered with the default values. Always use a subclass with constructor overrides. This follows the same pattern as DropDownMultiselect.

Subclassing​

The following protected properties and methods are available for override in subclasses:

MemberTypePurpose
localizationIAutocompleteLocalizationLocalization strings for button and placeholder
searchButtonOrderstringCSS class for search icon alignment (default: "", use "text-end" for right-aligned)
autocompleteSelectorButton (readonly)Internal invisible button that triggers the Bootstrap dropdown
searchFieldTextField (readonly)Internal text input for search queries
itemsAutocompleteItem[]Array of currently displayed result items
autocompleteGuiCommons (readonly)The dropdown menu container
searchButton (readonly)The search button
clearButton (readonly)The clear/reset button
searchToQuery($value)MethodOverride to transform search text to query (alternative to setSearchToQueryFormatter)
resultToValue($result)MethodOverride to transform result data to display text (alternative to setResultToValueFormatter)
getNewItemInstance()MethodOverride to return a custom AutocompleteItem subclass
fetchData()MethodOverride to customize the entire fetch-and-render cycle
innerHtml()MethodOverride to customize the component HTML structure

AutocompleteItem​

AutocompleteItem extends DropDownListItem and is the class used for each result in the dropdown. It can be subclassed for custom item rendering, and getNewItemInstance() can be overridden to return the custom subclass.

Complete Example​

A full example with fetchHandler, dataToItemMapper, onSearch, onSelect override, and custom formatters.

// Panel
public readonly employeeSearch : Autocomplete;

// Constructor
this.employeeSearch = new Autocomplete();
<!-- innerHtml() -->
<div class="col-6" data-oidis-bind="${this.employeeSearch}"></div>
// Controller — beforeLoad()
$instance.employeeSearch.Trigger = 2;
$instance.employeeSearch.ReloadOnClear = true;

$instance.employeeSearch.setResultToValueFormatter(($value : IAutocompleteData) : string => {
const emp : Employee = <Employee>$value.value;
return `${emp.FirstName} ${emp.LastName} (${emp.Department})`;
});

$instance.employeeSearch.Bind({
fetchHandler: async ($query : any) : Promise<IAutocompleteData[]> => {
const results : Employee[] = (await this.client.SearchEmployees($query)).data;
return results.map(($emp : Employee) : IAutocompleteData => ({
text: `${$emp.FirstName} ${$emp.LastName}`,
value: $emp
}));
},
onSearch: async ($query : IAutocompleteQuery) : Promise<void> => {
this.selectedEmployee = null;
await $instance.table.ShowData(true);
},
itemCreateFormatter: async ($item : AutocompleteItem, $index : number) : Promise<void> => {
$item.getEvents().setOnClick(() : void => {
this.selectedEmployee = <Employee>$item.Data().value;
$instance.employeeSearch.Value = `${this.selectedEmployee.FirstName} ${this.selectedEmployee.LastName}`;
$instance.employeeSearch.Data($item.Data());
$instance.employeeSearch.Hide();
});
},
onClear: async () : Promise<void> => {
this.selectedEmployee = null;
await $instance.table.ShowData(true);
}
});

See also: User Controls | Data Binding | Events and Validation