Skip to content

AisTypeAhead ​

AisTypeAhead implements the user interface for a typeahead search. AisTypeAhead is responsible for triggering a search and manipulating search results. Search details are delegated to a search service letting the component accommodate both client-side and server-side searches.

v-model: GrayCooper5
Selected object:

Props ​

modelValue ​

Use the v-model directive to bind to a typeahead's value. v-model will return the value to identify the selected search result. That value corresponds to the attribute specified by the lookup prop. The search service will use the lookup() method to initialize the selection from the value. See Vue's v-model documentation for details.

service ​

The required service prop takes an instance of a search service that will transform a search query into search results. The service object must implement the interface detailed below which is responsible for looking up a specific result, executing a search for a query, sorting results, and formatting a result as a string.

lookup ​

The required lookup prop captures the attribute name in a search result object that can be used to identify a specific record. When a record is selected, the value of this attribute will be emitted with the update:modelValue event and bound with v-model. As an example, if your search result object models a person and your business key is represented by the attribute hawk_id, you would specify lookup="hawk_id". You would then get the person's HawkId bound to v-model.

placeholder ​

The input field's placeholder attribute. The default value is 'Search...'.

disabled ​

Use the disabled boolean prop to disable the typeahead.

hideBusy ​

hideBusy is a boolean prop. By default, AisTypeAhead will show a busy status icon when searching for potential results. For longer queries, this lets users know that the typeahead is working and for local queries you don't see the indicator at all. However, the indicator can be distracting for requests that are in the range of 50 to 100 milliseconds. In these cases, add hideBusy to remove the indicator as the interaction is already fast enough. You can use simulatedDelay in the example below to explore the issue.

lag ​

The amount of time (in milliseconds) to debounce search requests. The default value is 250 milliseconds.

clearButtonLabel ​

Provide a text label for screen readers for the button that clears the selected value. Default value is Clear selection.

highlight ​

The highlight prop accepts a Tailwind CSS background color class used to highlight the active result. The default value is bg-ui-gray-50. Do not deviate from this brand color without a compelling business reason.

simulatedDelay ​

simulatedDelay is a testing prop that allows developers to introduce a delay (in milliseconds) into the request that brings back the list of potential results. The default value is 0 and no delay will be added. You should not use a delay in production. Adding a delay can help you test the user experience under non-ideal network conditions.

Events ​

update:modelValue ​

Emitted when a search result is selected. The event contains the selected value as its payload. The attribute returned from the result object is specified by the lookup prop. Typically, v-model is used to sync typeahead selections.

@load ​

The @load event fires when the type ahead is loaded. The event's payload contains the value returned from the search service's lookup method. The payload will typically be an object and not the primitive value emitted by v-model.

@load may be used to capture the selected object or to trigger additional initialization logic. See the code example above to see how the two events work together.

@change ​

The @change event fires every time the typeahead's value changes. This happens both when a new value is selected and also when an existing value is cleared. The event's payload contains an object returned from the search service's execute method. The payload will typically be an object and not the primitive value emitted by v-model. This is what makes @change different from @update:modelValue.

@change may be used to capture the selected object or to trigger additional work. When capturing the selected object, use @load to initialize the selection. Notice how both v-model and selectedObject have a value on page load in the example above.

@select ​

The @load event fires when the user selects a new value from the typeahead's list. The event's payload contains an object returned from the search service's execute method. The payload will typically be an object and not the primitive value emitted by v-model.

The @select event enables a common pattern illustrated below where a typeahead is used to populate a list of results. In this use case, it is useful to clear the previous selection, so the component is ready to immediately accept input from the user.

Selected users: []
Last Selected:

Slots ​

default ​

The default slot is used to customize the typeahead's search results. The slot exposes the result object through the slot prop item. You can destructure the prop like this: <template #default="{item}"> or change the name like: <template #default="{item: person}">. The slot also exposes selected, active, and disabled attributes.

By default the typeahead uses the service's formatted string for display. Additionally, the AisTypeAheadEntry component provides a more structured display and serves as a model for other customizations.

v-model:LatrenaCooper18
@change:{}

Search Service ​

AisTypeAhead requires a service object to power its search results. Specifically, a service object is responsible for looking up a specific result, executing a search for the supplied query, formatting a result as a string, and optionally sorting the results. These responsibilities are fulfilled by implementing the following interface.

js
export default class ExampleSearch {

  /**
   * value: key value to lookup a specific record
   *
   * example usage:
   *   service.lookup('jburbidge')
   */
  async lookup(value:String|Number) : Object {}

  /**
   * query: search query entered in the input
   *
   * Returns an object containing an array of search results:
   * { results: Array[Object] }
   */
  async execute(query:String) : Array[Object] {}

  /**
   * format a specific search result object for display
   */
  format(searchResult:Object) : String {}

  /**
   * sort (optional) returns a boolean, an array of sort keys, or a function to be
   * passed to Array.sort()
   * 
   * If sort() is not defined, results will be returned in their existing order.
   * This is useful for sorting on the server.
   * 
   * To sort by the formatted string, return true from sort(). This is useful if
   * format() already defines a natural string ordering. 
   * 
   * The array form, uses the same sorting style as AisTable. Assuming results of
   * the shape: { first, last, age, address: {city}}, we can use the following 
   * sort definitions:
   * 
   * - ['last', 'first'] // Sort by last then first ascending
   * - ['-age', 'first'] // Sort by age descending then first
   * - ['address.city', 'first'] // Sort by city then first.
   * 
   * If you need more control, sort() should return a function that will be passed
   * directly to Array.sort on the results from execute(). See MDN for details 
   * on Array.sort():
   * 
   * - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
   */
  sort() : Boolean | Array[String] | Function {}
}

Guidance ​

Packaging ​

Typeahead searches are often used in multiple locations. In this case, it makes sense to package the search service and typeahead configuration into its own component. This makes it easy to drop a fully-functioning search onto a page.

Scoping ​

Creating a new component also adds the ability to take in extra props and dynamically scope searches. As an example, say your application manages people affiliated with departments. You can have your new component take a department prop such that the search only returns people associated with that department. A rudimentary example of this is shown below.

Scope results to selected department
Type 'e' to see scoped results
v-model:
@change:

Clear on selection ​

A common typeahead use case is to populate a list. In this case, it makes sense to add the item to the list and clear the selection, so the typeahead is ready for the next search. To accomplish this, developers may add an @change handler where they can process the selection and then set the model ref to null.

There are two caveats to keep in mind here. One, once you clear the model, another @change event will fire with an empty value. Your handler should ignore this case. The second gotcha is caused by a bug in the component where null or '' will trigger the expected behavior but undefined does not trigger the presence of a new value and update the internal state as expected.

v-model:
Selected object: