TypeaheadSearch
A search form with stylized autocomplete suggestions.
TypeaheadSearch contains a form with a text input, a submit button, and a slot for hidden inputs. The parent component must listen for changes in the search query (which are debounced by default), fetch or calculate search results, then provide them as an array of suggestions for display to the user as a menu of ListTiles.
At the end of the list of suggestions, a final option to go to the search page for the current search query is provided.
Events are emitted to the parent when a suggestion is selected and when the form is submitted, with data about the selected suggestion (e.g. for analytics).
TextInput props apply
This component contains a TextInput component. You can bind TextInput props to this component and they will be passed to the TextInput within.
Attributes passed to input
This component will pass any HTML attributes applied to it, except for CSS class, to the <input>
element within the component.
Demos
Default
This basic example computes suggestions on input and passes them back to the TypeaheadSearch component. Open the console to see emitted events.
<template>
<div>
<cdx-typeahead-search
id="tahs-default"
form-action="https://en.wikipedia.org/w/index.php"
button-label="Search"
suggestions-label="Search results"
:suggestions="suggestions"
:search-footer-url="searchFooterUrl"
:highlight-query="true"
placeholder="Search for things starting with 'Co'"
@new-input="onNewInput"
@suggestion-click="onSuggestionClick"
@submit="onSubmit"
>
<template #default>
<input
type="hidden"
name="language"
value="en"
>
<input
type="hidden"
name="title"
value="Special:Search"
>
</template>
<template #search-footer-text="{ searchQuery }">
Search Wikipedia for pages containing
<strong class="cdx-typeahead-search__search-footer__query">
{{ searchQuery }}
</strong>
</template>
</cdx-typeahead-search>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { CdxTypeaheadSearch } from 'vue-components/src/lib';
import { SearchResult, SuggestionClickEvent } from 'vue-components/src/types';
import searchResults from './searchResults';
export default defineComponent( {
name: 'TypeaheadSearchDefault',
components: { CdxTypeaheadSearch },
setup() {
const suggestions = ref<SearchResult[]>( [] );
const searchFooterUrl = ref( '' );
function onNewInput( value: string ) {
console.log( '"new-input" event emitted with value: ' + value );
if ( value ) {
suggestions.value = ( searchResults as SearchResult[] ).filter( ( result ) => {
return result.label?.toLowerCase().includes( value.toLowerCase() );
} );
searchFooterUrl.value = `https://en.wikipedia.org/w/index.php?title=Special:Search&fulltext=1&search=${encodeURIComponent( value )}&ns0=1`;
} else {
suggestions.value = [];
searchFooterUrl.value = '';
}
}
function onSuggestionClick( event: SuggestionClickEvent ) {
console.log( '"suggestion-click" event emitted with value:' );
console.log( event );
}
function onSubmit( event: SuggestionClickEvent ) {
console.log( '"submit" event emitted with value:' );
console.log( event );
}
return {
suggestions,
searchFooterUrl,
onNewInput,
onSuggestionClick,
onSubmit
};
}
} );
</script>
TypeaheadSearch has a prop, initialInputValue
, that can be used to pass in the initial value of the TextInput. This is useful when replacing a server-rendered UI where the user may have started typing a search query.
On mount, TypeaheadSearch will fetch suggestions for the initial input value if it's provided. After that, the input value is tracked internally and will be emitted up to the parent component when the value changes.
<template>
<div>
<cdx-typeahead-search
id="tahs-initial-value"
form-action="https://en.wikipedia.org/w/index.php"
button-label="Search"
suggestions-label="Search results"
initial-input-value="Colora"
:suggestions="suggestions"
:search-footer-url="searchFooterUrl"
:highlight-query="true"
placeholder="Search for things starting with 'Co'"
@new-input="onNewInput"
>
<template #search-footer-text="{ searchQuery }">
Search Wikipedia for pages containing
<strong class="cdx-typeahead-search__search-footer__query">
{{ searchQuery }}
</strong>
</template>
</cdx-typeahead-search>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { CdxTypeaheadSearch } from 'vue-components/src/lib';
import { SearchResult } from 'vue-components/src/types';
import searchResults from './searchResults';
export default defineComponent( {
name: 'TypeaheadSearchInitialValue',
components: { CdxTypeaheadSearch },
setup() {
const suggestions = ref<SearchResult[]>( [] );
const searchFooterUrl = ref( '' );
function onNewInput( value: string ) {
if ( value ) {
suggestions.value = ( searchResults as SearchResult[] ).filter( ( result ) => {
return result.label?.toLowerCase().includes( value.toLowerCase() );
} );
searchFooterUrl.value = `https://en.wikipedia.org/w/index.php?title=Special:Search&fulltext=1&search=${encodeURIComponent( value )}&ns0=1`;
} else {
suggestions.value = [];
searchFooterUrl.value = '';
}
}
return {
suggestions,
searchFooterUrl,
onNewInput
};
}
} );
</script>
Without thumbnails
Use the hideThumbnail
prop if the suggestions will not have thumbnails.
<template>
<div>
<cdx-typeahead-search
id="tahs-hide-thumbnails"
form-action="https://en.wikipedia.org/w/index.php"
button-label="Search"
suggestions-label="Search results"
:suggestions="suggestions"
:search-footer-url="searchFooterUrl"
:highlight-query="true"
:hide-thumbnail="true"
placeholder="Search for things starting with 'Co'"
@new-input="onNewInput"
>
<template #search-footer-text="{ searchQuery }">
Search Wikipedia for pages containing
<strong class="cdx-typeahead-search__search-footer__query">
{{ searchQuery }}
</strong>
</template>
</cdx-typeahead-search>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { CdxTypeaheadSearch } from 'vue-components/src/lib';
import { SearchResult } from 'vue-components/src/types';
import searchResults from './searchResults';
export default defineComponent( {
name: 'TypeaheadSearchHideThumbnails',
components: { CdxTypeaheadSearch },
setup() {
const suggestions = ref<SearchResult[]>( [] );
const searchFooterUrl = ref( '' );
function onNewInput( value: string ) {
if ( value ) {
suggestions.value = ( searchResults as SearchResult[] ).filter( ( result ) => {
return result.label?.toLowerCase().includes( value.toLowerCase() );
} );
searchFooterUrl.value = `https://en.wikipedia.org/w/index.php?title=Special:Search&fulltext=1&search=${encodeURIComponent( value )}&ns0=1`;
} else {
suggestions.value = [];
searchFooterUrl.value = '';
}
}
return {
suggestions,
searchFooterUrl,
onNewInput
};
}
} );
</script>
Usage
Props
Prop name | Description | Type | Values | Default |
---|
id | ID attribute for the form. | string | - | |
formAction | Action attribute for form. | string | - | |
buttonLabel | Submit button text. | string | - | |
suggestionsLabel | Label attribute for the list of suggestions. | string | - | |
suggestions | List of suggestions. See the SearchResult type. | SearchResult[] | - | () => [] |
initialInputValue | Initial value for the text input.
Triggers an initial new-input event on mount. | string | - | '' |
searchFooterUrl | Link for the final suggestion.
This will typically be a link to the search page for the current search query. | string | - | '' |
debounceInterval | Time interval for debouncing input events, in ms. | number | - | DebounceInterval |
highlightQuery | Whether the search query should be highlighted within a suggestion's title. | boolean | - | false |
hideThumbnail | Whether to hide suggestions' thumbnails. | boolean | - | false |
hideDescription | Whether to hide suggestions' descriptions. | boolean | - | false |
Events
Event name | Properties | Description |
---|
new-input | value string - The new input value | When the text input value changes. Debounced by default. |
suggestion-click | event SuggestionClickEvent - Data for the selected suggestion | When a suggestion is selected. |
submit | event SuggestionClickEvent - Data for the selected suggestion | When the form is submitted. |
Slots
Name | Description | Bindings |
---|
search-footer-text | A slot for passing in translated search footer text, i.e. Search for pages containing<strong class="cdx-typeahead-search__search-footer__query"></strong> | searchQuery string - Input text entered by the user |
default | A slot for passing hidden inputs, i.e. <input type="hidden" name="language" value="en"> | |