Слоты
Примечание
Vs Vue3 Select использует слоты для более гибкой настройки уровня представления. Слоты можно использовать для изменения внешнего вида пользовательского интерфейса или просто для замены текста
footer
Отображается внизу компонента, ниже .vs__dropdown-toggle
.
При реализации этого слота вам, возможно, потребуется использовать appendToBody
для позиционирования выпадающего списка. Иначе содержимое в этом слоте повлияет на его позиционирование
search {string}
- текущий поисковый запросloading {boolean}
- признак состояния загрузкиsearching {boolean}
- признак состояния поискаfilteredOptions {array}
- массив опций отфильтрованных поисковым запросомdeselect {function}
- функция отменяющая выбор опции
export type DeselectFunction = (option: object | number) => void;
export interface FooterSlotProps {
search: string;
loading: boolean;
searching: boolean;
filteredOptions: [];
deselect: DeselectFunction;
}
<template>
<v-select append-to-body>
<template #footer>
<div style="opacity: 0.8">
Bottom of the component, in the footer slot!
</div>
</template>
</v-select>
</template>
header
Отображается вверху компонента, перед .vs__dropdown-toggle
.
search {string}
- текущий поисковый запросloading {boolean}
- признак состояния загрузкиsearching {boolean}
- признак состояния поискаfilteredOptions {array}
- массив опций отфильтрованных поисковым запросомdeselect {function}
- функция отменяющая выбор опцииinputId {string}
- Атрибут id элемента input v1.2.0+selectedValue {array}
- Массив выбранных опций v1.2.0+open {bool}
- Индикатор активности поля v1.2.0+
export type DeselectFunction = (option: object | number) => void;
export interface HeaderSlotProps {
search: string;
loading: boolean;
searching: boolean;
filteredOptions: [];
deselect: DeselectFunction;
inputId: string;
selectedValue: [];
open: boolean;
}
<template>
<v-select>
<template #header>
<div style="opacity: 0.8">Top of the component, in the header slot!</div>
</template>
</v-select>
</template>
list-footer
Отображается последним элементом списка. Не имеет контента по умолчанию. Родительский элемент <ul>
, таким образом данный слот должен иметь в качестве корня тег <li>
.
search {string}
- текущий поисковый запросloading {boolean}
- признак состояния загрузкиsearching {boolean}
- признак состояния поискаfilteredOptions {array}
- массив опций отфильтрованных поисковым запросом
export interface ListFooterSlotProps {
search: string;
loading: boolean;
searching: boolean;
filteredOptions: [];
}
<template>
<v-select>
<template #list-footer>
<li style="text-align: center">Bottom of the list!</li>
</template>
</v-select>
</template>
list-header
Отображается первым элементом списка. Не имеет контента по умолчанию. Родительский элемент <ul>
, таким образом данный слот должен иметь в качестве корня тег <li>
.
search {string}
- текущий поисковый запросloading {boolean}
- признак состояния загрузкиsearching {boolean}
- признак состояния поискаfilteredOptions {array}
- массив опций отфильтрованных поисковым запросом
export interface ListHeaderSlotProps {
search: string;
loading: boolean;
searching: boolean;
filteredOptions: [];
}
<template>
<v-select>
<template #list-header>
<li style="text-align: center">Top of the list!</li>
</template>
</v-select>
</template>
no-options
Слот отображающий отсутствие опций. Размещает в выпадающем списке перед list-footer
когда filteredOptions.length === 0
.
search {string}
- текущий поисковый запросloading {boolean}
- признак состояния загрузкиsearching {boolean}
- признак состояния поиска
export interface NoOptionsSlotProps{
search: string;
loading: boolean;
searching: boolean;
}
<template>
<v-select>
<!-- eslint-disable-next-line vue/no-unused-vars -->
<template #no-options="{ search, searching, loading }">
This is the no options slot.
</template>
</v-select>
</template>
open-indicator
Индикатор состояния выпадающего списка.
attributes = {
ref: 'openIndicator',
role: 'presentation',
class: 'vs__open-indicator'
}
interface OpenIndicatorSlotProps extends VNodeProps {
attributes: {
[key: string]: any;
};
}
<template>
<v-select>
<template #open-indicator="{ attributes }">
<span v-bind="attributes">🔽</span>
</template>
</v-select>
</template>
option
Отдельный элемент выпадающего списка, содержащийся в <li>
.
option {Object}
- текущая опция в цикле поfilteredOptions
<template>
<v-select :options="books" label="title">
<template #option="{ title, author }">
<strong style="display:block;margin: 0">{{ title }}</strong>
<em>{{ author.firstName }} {{ author.lastName }}</em>
</template>
</v-select>
</template>
<script>
export default {
data: () => ({
books: [
{
title: "Old Man's War",
author: {
firstName: 'John',
lastName: 'Scalzi',
},
},
],
}),
}
</script>
search
Строка ввода поискового запроса множество привязок, но они сгруппированы: атрибуты и события. В большинстве случаев достаточно привязывать эти два параметра с помощью v-on="events" и v-bind="attributes".
Если необходимо сохранить стиль по умолчанию, то добавьте классы vs__search vs__search_position
к добавляемому полю ввода. Класс vs__search_position
синхронизирует позицию текста поиска и текста автодополнения.
/**
* Атрибуты привязываемые к полю ввода.
*/
attributes = {
disabled: this.disabled,
placeholder: this.searchPlaceholder,
tabindex: this.tabindex,
readonly: !this.searchable,
id: this.inputId,
'aria-autocomplete': 'list',
'aria-labelledby': `vs${this.uid}__combobox`,
'aria-controls': `vs${this.uid}__listbox`,
'aria-activedescendant': this.typeAheadPointer > -1
? `vs${this.uid}__option-${this.typeAheadPointer}`
: '',
ref: 'search',
type: 'search',
autocomplete: this.autocomplete,
value: this.search,
},
/**
* События, которые должен обрабатывать этот элемент
*/
events = {
'compositionstart': () => this.isComposing = true,
'compositionend': () => this.isComposing = false,
'keydown': this.onSearchKeyDown,
'blur': this.onSearchBlur,
'focus': this.onSearchFocus,
'input': (e) => this.search = e.target.value,
}
interface SearchSlotProps extends VNodeProps {
attributes: {
[key: string]: any;
};
events: {
compositionstart: () => void;
compositionend: () => void;
keydown: (event: KeyboardEvent) => void;
blur: (event: FocusEvent) => void;
focus: (event: FocusEvent) => void;
input: (event: InputEvent) => void;
};
}
<template>
<v-select>
<template #search="{ attributes, events }">
<input
maxlength="1"
class="vs__search"
v-bind="attributes"
v-on="events"
/>
</template>
</v-select>
</template>
selected-option
Текст отображаемый внутри selected-option-container
.
Этот слот не существует если реализован selected-option-container
option {Object}
- Выбранная опция
<template>
<v-select v-model="selected" :options="books" label="title">
<template #selected-option="{ title, author }">
<div style="display: flex; align-items: baseline">
<strong>{{ title }}</strong>
<em style="margin-left: 0.5rem;opacity:0.7">by {{ author.firstName }} {{ author.lastName }}</em>
</div>
</template>
</v-select>
</template>
<script>
const book = {
title: "Clean Architecture",
author: {
firstName: 'Robert',
lastName: 'Martin',
},
}
export default {
data: () => ({
books: [
book,
{
title: "Old Man's War",
author: {
firstName: 'John',
lastName: 'Scalzi',
},
}
],
selected: book,
}),
}
</script>
selected-option-container
Это корневой элемент где v-for="option in selectedValue"
. В большинстве случаев достаточно использовать selected-option
, но этот контейнер полезен, если вы хотите отключить кнопку отмены выбора или иметь точный контроль над разметкой.
option {Object}
- Текущая выбранная опцияdeselect {Function}
- Метод, используемый для отмены выбора данной опции, когда значениеmultiple
равно truedisabled {Boolean}
- Флаг заблокированного состояния компонентаmultiple {Boolean}
- Флаг поддержки компонентом множественного выбора
export interface SelectedOptionContainerSlotProps {
option: object | string;
deselect: DeselectFunction;
disabled: boolean;
multiple: boolean;
}
<template>
<!-- eslint-disable vue/no-unused-vars -->
<v-select :options="books" label="title">
<template
#selected-option-container="{ option, deselect, multiple, disabled }"
>
<div class="vs__selected">{{ option.title }}</div>
</template>
</v-select>
</template>
<script>
export default {
data: () => ({
books: [
{
title: "Old Man's War",
author: {
firstName: 'John',
lastName: 'Scalzi',
},
},
],
}),
}
</script>
spinner
loading {Boolean}
- Флаг состояния загрузки данных
<template>
<v-select :loading="true">
<template #spinner="{ loading }">
<div
v-if="loading"
style="border-left-color: rgba(88, 151, 251, 0.71)"
class="vs__spinner"
>
The .vs__spinner class will hide the text for me.
</div>
</template>
</v-select>
</template>
typeahead
v1.2.0+
Строка автодополнения.
Если необходимо сохранить стиль по умолчанию, то добавьте классы vs__search_complete vs__search_position
к добавляемому элементу. Класс vs__search_position
синхронизирует позицию текста поиска и текста автодополнения.
search {string}
- Текст поискаcompletedText {string}
- Дополненный текст поискаsearching {Boolean}
- Флаг состояния поиска компонентаcanCompleteSearch {Boolean}
- Признак режима автодополнения
<script setup>
const options = ['Albania', 'Algeria', 'American Samoa',
'Andorra', 'Angola', 'Anguilla', 'Antarctica'];
</script>
<template>
<v-select
:options="options"
:auto-select="true"
:complete-search="true"
>
<template v-slot:typeahead="{ canCompleteSearch, completedText }">
<div class="vs__search_position vs__search_complete"
v-if="canCompleteSearch && completedText!==''">
{{ completedText }}
<small> will be selected</small>
</div>
</template>
</v-select>
</template>