DaData-suggestions component for Vue 3
Try the demo playground to understand how it works.
Demo
Install
npm install @dadata-sdk/vuepnpm add @dadata-sdk/vueOr install from the latest commit on GitHub:
pnpm add @dadata-sdk/vue@github:alexchexes/dadata-sdk#rewritten&path:/packages/vue-dadataUsage
<script setup>
import { ref } from 'vue';
import { VueDadata } from 'vue-dadata';
// use shipped CSS if needed:
import 'vue-dadata/dist/vue-dadata.css';
const token = import.meta.env.VITE_APP_DADATA_API_KEY; // API key
const query = ref(''); // input field value
const suggestion = ref(undefined); // selected suggestion
</script>
<template>
<VueDadata v-model="query" v-model:suggestion="suggestion" :token="token" />
</template>V-Models
v-model
- Required
- Type:
string
The v-model for the query text. The value is used in API calls and is synced with the input field (<input>) all the time, except when navigating suggestions with keyboard (↑↓ keys) — during such a navigation, the input field displays the text from the currently navigated (highlighted) suggestion, while the v-model value retains the text that was in the field before navigation began. After a suggestion is selected or navigation ends (Esc, click outside), the field will be in sync with the v-model value again.
v-model:suggestion
- Type:
object | undefined
The v-model for the currently selected suggestion object. Provides easy access to the object and works both ways — you can set an "initial" suggestion on page-load without an extra API call. When a non-empty object is set from outside, the v-model for the query text will also be updated.
Props
General options
token
string
Your DaData API key (token).
suggestType
string
Type of suggestions (Dadata suggest API endpoint):
address- Normal addresses https://dadata.ru/api/suggest/address/fias- FIAS addresses (discouraged by Dadata) https://dadata.ru/api/suggest/fias/party- Legal entities https://dadata.ru/api/suggest/party/bank- Finance organizations https://dadata.ru/api/suggest/bank/fio- Names, surnames, patronymics https://dadata.ru/api/suggest/name/email- Email address https://dadata.ru/api/suggest/email/
Default address
httpCache
boolean
If false, HTTP requests will not be cached.
Default true
url
string
Custom API URL.
Useful when proxying requests to the DaData API.
Note: currently the endpoint (i.e. suggestType) is not appended automatically.
You must provide the full URL, e.g. https://my-api-proxy.example.com/suggest/address.
Default: The final URL is built from the base DaData suggest API (.../api/4_1/rs/suggest/) + suggestType.
payload
OptionalSuggestPayload (object)
Custom payload for the API request.
Any fields specified here will be added to the final request payload, or override existing values if already set.
headers
PlainHeaders (object)
Custom headers for the API request.
Any headers specified here will be added to the final request headers, or override existing values if already set.
Request options (address)
count
number
Maximum number of suggestion items to fetch from the DaData API.
Max: 20, Default: 10
locationsBoost
KladrIdFilter (object) | string | number | array
kladr_id or an array of kladr_ids for the region/city to be prioritized in suggestions.
Corresponds to the locations_boost API parameter.
Examples:
-
55— Omsk region -
63000001— Samara city -
6300000100000— Samara city (full KLADR code) -
[50, 77]— Moscow and Moscow-City regions -
{kladr_id: '02'}or[{kladr_id: '02'}, ...]— native DaData API format -
'address': https://confluence.hflabs.ru/pages/viewpage.action?pageId=285343795
-
'fias': https://confluence.hflabs.ru/pages/viewpage.action?pageId=968425529
Max: 10 items
locationsFilter
LocationRestriction (object) | string | number | array
Restricts the search to specific locations (API locations parameter).
Max: 10 items
For example (when suggestType=address), to search only in Voronezh city and in Rostov region:
:locationsFilter="[{'region':'Воронежская','city':'Воронеж'},{'region':'Ростовская'}]"
- For
address: https://confluence.hflabs.ru/pages/viewpage.action?pageId=204669108 - For
fias: https://confluence.hflabs.ru/pages/viewpage.action?pageId=967835974
For party and bank, the only supported filter is kladr_id.
fromBound
string
Limits the type of address object from which DaData begins searching:
country|region|area|city|settlement|planning_structure|street|house
Corresponds to the from_bound API parameter.
toBound
string
Limits the type of address object to which DaData performs the search:
country|region|area|city|settlement|planning_structure|street|house|flat
Corresponds to the to_bound API parameter.
https://confluence.hflabs.ru/pages/viewpage.action?pageId=222888017
restrictValue
boolean
Used with locationsFilter. If true, the displayed suggestion (i.e., value field)
will exclude address parts up to the restricted level.
For example, if the filter specifies a region, that region will be omitted in the result;
if it specifies a city, both the region and city will be omitted.
Corresponds to the restrict_value API parameter.
- https://confluence.hflabs.ru/pages/viewpage.action?pageId=222888017
- https://confluence.hflabs.ru/pages/viewpage.action?pageId=968425521
- https://confluence.hflabs.ru/pages/viewpage.action?pageId=1023737934#id-Ограничениепоназваниюадресногообъекта-Адресбезрегионаигорода
- https://confluence.hflabs.ru/display/SGTDOC/address.value#address.value-Параметрrestrict_value
radiusFilter
RadiusFilter (object)
Restrict the search to a specific radius around a latitude/longitude point.
Example: {lat: '59.244634', lon: '39.913355', radius_meters: 200}
Corresponds to the locations_geo API parameter.
See https://confluence.hflabs.ru/pages/viewpage.action?pageId=990871806
division
string
Type of territorial division: ADMINISTRATIVE or MUNICIPAL:
ADMINISTRATIVE:Московская обл, г Одинцово, село НикольскоеMUNICIPAL:Московская обл, г.о. Одинцовский, село Никольское
Also affects set of fields inside suggestion.data
@default 'ADMINISTRATIVE'
See https://confluence.hflabs.ru/pages/viewpage.action?pageId=1326056589
language
string
Display language for address suggestions. RU or EN.
EN is almost always simple transliteration to latin script,
however, for some cities, like "Moscow", fields will be translated to English,
including the city type ("city", while for others it's often "gorod").
Default: RU.
@default 'RU'.
https://confluence.hflabs.ru/pages/viewpage.action?pageId=976388726
Request options (other)
entityType
string | (string | array) | (string | array) | (string | array)
Organization or bank type (for party, party_by, party_kz, and bank suggestions).
for party: LEGAL or INDIVIDUAL, https://confluence.hflabs.ru/pages/viewpage.action?pageId=206176337
-
for
bank: https://confluence.hflabs.ru/pages/viewpage.action?pageId=262996122 -
for
party_by: https://dadata.ru/api/suggest/party_by/ -
for
party_kz: https://dadata.ru/api/suggest/party_kz/
entityStatus
(string | array) | (string | array) | (string | array)
Organization or bank status (for party, party_by and bank suggestions)
'ACTIVE' | 'LIQUIDATING' | 'LIQUIDATED' | etcparty: https://confluence.hflabs.ru/pages/viewpage.action?pageId=206176335party_by: https://dadata.ru/api/suggest/party_by/bank: https://confluence.hflabs.ru/pages/viewpage.action?pageId=262996120
branchType
string | array
Branch type filter (for party suggestions)
MAIN- to search only for head officesBRANCH- search only for branches
See https://confluence.hflabs.ru/pages/viewpage.action?pageId=568918095
okved
string | array
OKVED code filter (for party suggestions). Max: 10 items
fioParts
string | array
Filter by FIO parts (for fio suggestions, see https://dadata.ru/api/suggest/name/).
Examples:
- Names only:
['NAME']orNAME - Names and patronymics:
['NAME', 'PATRONYMIC'] - Names and surnames:
['NAME', 'SURNAME']
fioGender
string
Filter by gender (for fio suggestions).
UNKNOWN/MALE/FEMALE
filters
SuggestFmsUnitFilter (object) | SuggestFnsUnitFilter (object) | SuggestMetroFilter (object) | SuggestMktuFilter (object) | SuggestOkpd2Filter (object) | SuggestOkved2Filter (object) | SuggestPartyByFilter (object) | SuggestPartyKzFilter (object) | SuggestPostalUnitFilter (object) | SuggestCourtFilter (object) | array
Filters for APIs that don't have dedicated options props,
like fms_unit, fns_unit, metro, mktu, okpd2, okved2, postal_unit, court.
To set filters for party_by and party_kz use entityStatus and entityType options, just like for normal party.
Component behavior
debounce
number
Delay (in ms) after changing the input (query) before sending the request.
Works on the principle of debounce: if the input continues to change,
the request will not be sent until this number of milliseconds has passed
since the last change.
Default 100
minChars
number
Minimum length of input after which suggestions are triggered.
Default 1
disabled
boolean
Sets the disabled attribute on the input element, disables suggestions and all interactions.
Default false
placeholder
string
Text used for the input's placeholder attribute.
inputName
string
Value for the input's name attribute.
Default dadata-input
inputAttributes
suggestionsHint
string
Text to show above the suggestions list
noSuggestionsHint
string | boolean
Text to show in place of suggestions when there are no suggestions. Pass true
if you use the hint slot for displaying a custom "no-suggestions" design to keep it visible.
classes
VueDadataClasses (object)
Custom CSS classes names for component elements.
Defaults: DEFAULT_CLASSES
showOnFocus
string | boolean
Controls when to show the dropdown with suggestions list on input focus.
false: Never show dropdown on focus'always': Always show dropdown on focus (if input and suggestions list is not empty).'no_selection': Show dropdown on focus when there's no selected suggestion
Default: 'no_selection'
selectOnBlur
boolean
If true, the first suggestion will be auto-selected after input lost focus.
Default: false
selectOnEnter
boolean
If true, pressing Enter selects the first suggestion (if list is open).
Default: true
enrichOnSelect
boolean
Whether to send an additional request after a suggestion is selected to enrich it with
data like geo_lat, geo_lon, city_district (and full value when restrictValue is used).
Set to false if you want to save API usage and don’t need that data.
Default: true
clearOnChange
string | boolean
Determines whether the suggestion (i.e., v-model:suggestion) is cleared when the input changes after a suggestion is selected.
false: The suggestion is never cleared when the input changes.'any': The suggestion is cleared whenever input value is changed.'significant': The suggestion is cleared only if the new input, after being normalized (i.e., trimmed and case-normalized), differs from the previous value.
Default: 'significant'
addSpace
boolean
If true, adds a space to the input after a suggestion is selected. This way, for example,
user can select street and then type house number without adding a space by himself.
Default true
continueSelecting
boolean
If true, the suggestions list will remain visible after selecting a suggestion.
Default: false
showClearButton
boolean
If true, shows a clear (×) button in the input when not empty.
Default: false
focusOnMounted
boolean
If true, input will be focused immediately when the component is mounted.
Default false
forceShow
boolean
Forces the suggestions list to always remain visible.
Useful during development (e.g., when styling elements).
Default: false
forceHide
boolean
Forces the suggestions list to always remain hidden.
Default: false
Emitted events
| Event | When emitted | Event payload type |
|---|---|---|
@error | In case of any error | unknown |
@select | When a suggestion is selected, either by click, by pressing "Enter", or automatically when selectOnBlur=true | (suggestion: object, selectType: string) |
@enriched | When selected suggestion was enriched (when enrichOnSelect=true) | (suggestion: object, diff: object | null) |
@enrichFail | When attemp to enrich selected suggestion fails (when enrichOnSelect=true) | string (suggestion.unrestricted_value) |
@focus | When input is focused | FocusEvent |
@blur | When input looses focus | FocusEvent |
Slots
The props of each slot receive
mergedClasses— an object containing all the CSS classes used by the component, in the same format as the object for theclassesprop on the component (VueDadataClasses).
inputWrapper
A slot for replacing the main visible container with the input field, including the <input> and the “clear” button.
The following props are passed to the slot:
coreInputProps— recommended tov-bindfully to your owninput. Includes essential event handlers required by the component:@input,@keydown,@focus,@blur, as well as thedisabledattribute andvalue, which does not always match the text inquery, as it may contain the currently visible text when navigating suggestions via keyboard.browserAutoProps— attributes for disabling browser features that interfere with normal usage: autofill, autocomplete, autocorrect, and spellcheck.allInputProps— includes everything fromcoreInputPropsandbrowserAutoProps, plus the attributestype,class,name, andplaceholder.mergedClasses— the CSS classes used by the component.
Example usage:
<template #inputWrapper="{ allInputProps, coreInputProps, browserAutoProps }">
<!-- Your custom input/wrapper/anything -->
<MyFancyInput
v-bind="{ ...coreInputProps, ...browserAutoProps }"
:placeholder="allInputProps.placeholder"
/>
</template>If desired, <input> can be replaced with <textarea> (bind coreInputProps the props to it in the same way).
input
Replaces only the <input>, without affecting the parent container or the overlay with the “clear” button. The slot props are the same as for inputWrapper. Example:
<template #input="{ allInputProps, coreInputProps, browserAutoProps }">
<textarea v-bind="allInputProps" />
</template>inputOverlay
An empty slot that allows you to add custom elements inside the container with the input, such as a loading indicator, buttons, etc. There are no props except mergedClasses. Example:
<template #inputOverlay>
<!-- Custom loading spinner, icons, buttons, etc -->
</template>clearButtonIcon
Replaces the icon of the built-in “clear” (×) button without affecting the <button> element itself. There are no props except mergedClasses. Example:
<template #clearButtonIcon>
<svg><!-- Custom "clear" icon --></svg>
</template>hint
This slot replaces the "hint" text shown above the suggestions list inside the dropdown and allows you to add custom elements to display there when suggestions are present, or instead of the list when nothing is found. For example, you can add a link or a button like "Reset filters," or apply custom styling to the suggestionsHint message (like “Choose an option or continue typing...”).
The container has @mousedown.prevent applied to prevent losing focus and hiding the dropdown when clicking inside the container.
To keep the dropdown visible when no suggestions are found, pass true to the component’s noSuggestionsHint prop.
Slot props:
suggestionsList— the current suggestions listsuggestionsHint— the hint text when suggestions are present (default or from the component'ssuggestionsHintprop)noSuggestionsHint— the hint text when no suggestions are found (from the component'snoSuggestionsHintprop)mergedClasses— the CSS classes used by the component
Example:
<!-- <VueDadata :noSuggestionsHint="true" ...> -->
<template #hint="{ suggestionsList, suggestionsHint, noSuggestionsHint }">
<!-- Default message when suggestions are found -->
<template v-if="suggestionsList.length"> {{ suggestionsHint }} </template>
<!-- Custom block when no suggestions are available -->
<template v-else>
Nothing found...
<button @click="reset">Reset filters?</button>
</template>
</template>suggestions
Replaces the entire suggestions list (without affecting hint and the dropdown container itself).
Slot props:
suggestionsList— an array of suggestion objectsnavigatedIndex— the index of the navigated suggestion (when navigating via keyboard)handleSuggestionClick— a click handler that must be added to each suggestion item to ensure full component functionality (add it with@mousedown.prevent="...")mergedClasses— the CSS classes used by the component
Example:
<template #suggestions="{ suggestionsList, navigatedIndex, handleSuggestionClick }">
<div
v-for="(suggestion, index) in suggestionsList"
:key="index"
@mousedown.prevent="handleSuggestionClick(index)"
>
{{ suggestion.value }}
</div>
</template>suggestionItem
Replaces whole suggestion item (including its container).
Slot props:
suggestion— the suggestion objectindex— the index of the item in the list (starting from0)isNavigated— whether this item is currently “highlighted” (during keyboard navigation)handleSuggestionClick— a click handler that must be added to each suggestion item to ensure full component functionality (add it with@mousedown.prevent="...")mergedClasses— the CSS classes used by the component
Example:
<template #suggestionItem="{ suggestion, index, isNavigated, handleSuggestionClick }">
<button @mousedown.prevent="handleSuggestionClick(index)">
{{ suggestion.value }}
</button>
</template>suggestionItemContent
Replaces the inner content of each suggestion item in the list, without affecting its parent container. The props are the same as for suggestionItem, except for handleSuggestionClick.
<template #suggestionItemContent="{ suggestion, index, isNavigated }">
{{ suggestion.value }}
</template>suggestionItemTitle
Replaces the element displaying the main text of the suggestion (suggestion.value). When using this slot, you’ll probably want to implement your own search text match highlighting — to get the highlighted chunks, you can use the highlightChunks function exported by the library.
The slot props are the same as for suggestionItem, except for handleSuggestionClick.
<template #suggestionItemTitle="{ suggestion, index, isNavigated }">
<!-- Show `unrestricted_value` instead of `value` (with custom `highlight`) -->
<span v-html="highlight(query, suggestion.unrestricted_value)" />
</template>suggestionItemSubtitle
Replaces the element used to display additional text below the main suggestion text. The default slot content appears only in certain cases, such as suggestions for party or bank, but this slot allows you to show extra info at any time.
The props are the same as for suggestionItem, except for handleSuggestionClick.
<template #suggestionItemSubtitle="{ suggestion, isNavigated }">
<div class="...">{{ suggestion.data.inn }}</div>
</template>Exposed Component API
The following methods and properties are available via the component's template ref (<VueDadata ref="vueDadata" ... />):
| Name | Type | Description |
|---|---|---|
inputRef | ShallowRef\<HTMLInputElement | null>\ | templateRef of the <input> element |
suggestionsList | Ref<DadataSuggestion[], DadataSuggestion[]> | The current list of suggestions or an empty array |
isDropdownVisible | ComputedRef<boolean> | true when the suggestion list is visible |
isFocused | ComputedRef<boolean> | true when the <input> is focused |
update() | (options) => DadataSuggestion[] | Sends an API request and updates the suggestions list. You can pass options to override the ones set via props. Returns fetched suggestions list or throws on any error. |
clear() | () => void | Clears the query text (modelValue), v-model:suggestion, and suggestionsList |
show() | () => void | Shows the dropdown (if there are suggestions available) |
hide() | () => void | Hides the dropdown |
focus() | () => void | Focuses the <input> |
blur() | () => void | Removes focus from the <input> |
Methods usage example
<script setup>
// ...
const query = ref('');
const suggestion = ref(undefined);
const vueDadata = useTemplateRef('vueDadata');
onMounted(async () => {
// `focus()`: Autofocus the input with a small delay after page load
setTimeout(() => {
vueDadata.value?.focus();
}, 300);
// set "selected suggestion" v-model manually
suggestion.value = {
/*...existing suggestion object...*/
};
// wait one tick so that v-model:suggestion propagates and changes the `query`
await nextTick();
// now fetch suggestions list with `update()`
const suggestions = await vueDadata.value?.update();
// the updated suggestions list is also available in the return value
console.log('Updated. Suggestions: ', suggestions);
// and finally use `show()` to open the dropdown programmatically
vueDadata.value?.show();
});
</script>
<template>
<VueDadata ref="vueDadata" v-model="query" v-model:suggestion="suggestion" ... />
<!-- Access to the fetched suggestions list -->
<pre>{{ vueDadata?.suggestionsList }}</pre>
</template>