🔍 Autosuggest component built for Vue.
Codesandbox Demos:
This module is distributed via npm which is bundled with node and
should be installed as one of your project's dependencies
:
npm install vue-autosuggest
or
yarn add vue-autosuggest
Load VueAutosuggest into your vue app globally.
import VueAutosuggest from "vue-autosuggest";
Vue.use(VueAutosuggest);
or locally inside a component:
import { VueAutosuggest } from 'vue-autosuggest';
export default {
...
components: {
VueAutosuggest
}
...
};
Place the component into your app!
<vue-autosuggest
:suggestions="[{data:['Frodo', 'Samwise', 'Gandalf', 'Galadriel', 'Faramir', 'Éowyn']}]"
:input-props="{id:'autosuggest__input', placeholder:'Do you feel lucky, punk?'}"
@input="onInputChange"
@selected="selectHandler"
@click="clickHandler"
>
<template slot-scope="{suggestion}">
<span class="my-suggestion-item">{{suggestion.item}}</span>
</template>
</vue-autosuggest>
Advanced usage:
```html
{{selected.name}}, the {{selected.race}}
For more advanced usage, check out the examples below, and explore the properties you can use.
Slots for injecting content around the results/input. Useful for header/footer like slots or empty state.
<vue-autosuggest ...>
<template slot="before-input"> content before the <input /> goes here </template>
<template slot="after-input"> content after the <input /> goes here </template>
<template slot="before-suggestions"> content before the <ul> goes here </template>
<template slot="before-section-<section.name e.g. 'default'>"> section header content for specific section goes here </template>
<template slot="after-section-<section.name e.g. 'default'>"> footer content goes here for specific section. </template>
<template slot="after-section"> Default footer content for all sections </template>
<template slot="after-suggestions"> content after the <ul> goes here </template>
</vue-autosuggest>
It is common in forms to add a label next to the <input />
tag for semantic html / accessibility. You can use the
before-input
slot to accomplish this in conjunction with the inputProps.id
:
<vue-autosuggest ...>
<template slot="before-input">
<label :for="inputProps.id">Search here:</label>
</template>
...
</vue-autosuggest>
Used to style each suggestion inside the <li>
tag. Using scoped slots
you have access to the suggestion
item inside the v-for
suggestions loop. This gives you the power of Vue templating, since
vue-autosuggest does not have an opinion about how you render the items in your list.
<vue-autosuggest>
<template slot-scope="{suggestion}">
<!-- suggestion.name corresponds to which section the item is in -->
<div v-if="suggestion.name === 'blog'">
<!-- suggestion.item corresponds to the suggestion object -->
<a target="_blank" :href="https://github.com/darrenjennings/vue-autosuggest/blob/master/suggestion.item.url">{{suggestion.item.value}}</a>
</div>
<div v-else>{{suggestion.item}}</div>
</template>
</vue-autosuggest>
This slot will be overridden when the
render-suggestion
prop is used.
Prop | Type | Required | Description |
---|---|---|---|
suggestions |
Array | ✓ | Array of sections, each containing suggestions to be rendered. e.g.suggestions: [{data: ['harry','ron','hermione']}] |
input-props |
Object | ✓ | Add props to the <input> . |
section-configs |
Object | Define multiple sections <input> . |
|
render-suggestion |
Function | Tell vue-autosuggest how to render inside the <li> tag. Overrides what is inside the default suggestion template slot. |
|
get-suggestion-value |
Function | Tells vue-autosuggest what to put in the <input/> value |
|
should-render-suggestions |
Function | Tell vue-autosuggest if it should render the suggestions results popover | |
component-attr-id-autosuggest |
String | id of entire component |
|
component-attr-class-autosuggest-results-container |
String | class of container of results container |
|
component-attr-class-autosuggest-results |
String | class of results container |
|
component-attr-prefix |
String | prefix to be used for results item classes/ids. default: autosuggest |
Prop | Type | Required | Description |
---|---|---|---|
id |
String | ✓ | id attribute on <input> . |
Any DOM Props | * | You can add any props to <input> as the component will v-bind inputProps. Similar to rest spread in JSX. See more details here: https://vuejs.org/v2/api/#v-bind. The name attribute is set to "q " by default. |
Multiple sections can be defined in the sectionConfigs
prop which defines the control behavior for
each section.
Prop | Type | Required | Description |
---|---|---|---|
on-selected |
Function | ✓ | Determine behavior for what should happen when a suggestion is selected. e.g. Submit a form, open a link, update a vue model, tweet at Ken Wheeler etc. |
limit |
Number | Limit each section by some value. Default: Infinity |
Below we have defined a default
section and a blog
section. The blog
section has a component
type
of url-section
which corresponds to which component the Autosuggest loads. When type is not
defined, Vue-autosuggest will use a built in DefaultSection.vue
component.
sectionConfigs: {
'default': {
limit: 6,
onSelected: function(item, originalInput) {
console.log(item, originalInput, `Selected "${item.item}"`);
}
},
'blog': {
limit: 3,
type: "url-section",
onSelected: function() {
console.log("url: " + item.item.url);
}
}
}
This function can be used to tell vue-autosuggest how to render the html inside the <li>
tag when you do not want to use the
default template slot for suggestions but would rather have the power of javascript / jsx.
In its most basic form it just returns an object property:
renderSuggestion(suggestion) {
return suggestion.name;
},
But usually it returns a JSX fragment, which is transformed into a virtual node description with babel-plugin-transform-vue-jsx:
renderSuggestion(suggestion) {
return <div style={{ color: "red" }}>{suggestion.name}</div>;
},
If you're not using babel-plugin-transform-vue-jsx, you can create the virtual node description yourself:
renderSuggestion(suggestion) {
return this.$createElement('div', { 'style': { color: 'red'} }, suggestion.name);
},
This function will tell vue-autosuggest what to put in the <input/>
as the value.
getSuggestionValue(suggestion) {
return suggestion.item.name;
},
This function will tell vue-autosuggest if it should display the suggestions popover
/**
* @param {Array} size - total results displayed
* @param {Boolean} loading - value that indicates if vue-autosuggest _thinks_ that the
* the popover should be open (e.g. if user hit escape, or
* user clicked away)
* @returns {Boolean}
*/
shouldRenderSuggestions (size, loading) {
// This is the default behavior
return size >= 0 && !loading
}
Below are the list of supported events. @
is short-hand for
v-on.
Prop | Returns | Description |
---|---|---|
@selected |
suggestionItem, index | suggestion select handler. equivalent to sectionConfigs on-selected but for all items |
@input , @focus , @blur , etc. |
* | there is a transparent wrapper on the underlying <input /> so vue-autosuggest will use any DOM event you pass it for listening. This is implemented using v-on:<event> . |
@opened , @closed |
* | suggestions visibility handler, indicates when the suggestions are opened and closed. This is called alongside shouldRenderSuggestions. |
@item-changed |
suggestionItem, index | when keying through the results, this event signals which item is highlighted before being selected. |
For IE11 and below, some functionality may not work. For example, you will have to manually polyfill Node.prototype.contains
Thanks goes to these people (emoji key):
Darren Jennings 💻 📖 🚇 ⚠️ 🎨 💡 |
Evgeniy Kulish 💻 🎨 💡 ⚠️ |
Scott Smith 🐛 💻 ⚠️ |
Fernando Machuca 🎨 |
BerniML 💻 ⚠️ |
Kristoffer Nordström 💻 ⚠️ |
Dan Wilson 💻 |
---|
Thanks to @chuca for the logo design.
This project follows the all-contributors specification. Contributions of any kind welcome!
MIT