Слоты

Примечание

Vs Vue3 Select использует слоты для более гибкой настройки уровня представления. Слоты можно использовать для изменения внешнего вида пользовательского интерфейса или просто для замены текста

Отображается внизу компонента, ниже .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;
}
Bottom of the component, in the footer slot!
<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>

Отображается вверху компонента, перед .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;
}
Top of the component, in the header slot!
<template>
  <v-select>
    <template #header>
      <div style="opacity: 0.8">Top of the component, in the header slot!</div>
    </template>
  </v-select>
</template>

Отображается последним элементом списка. Не имеет контента по умолчанию. Родительский элемент <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>

Строка ввода поискового запроса множество привязок, но они сгруппированы: атрибуты и события. В большинстве случаев достаточно привязывать эти два параметра с помощью 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 равно true
  • disabled {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>&nbsp;&nbsp;&nbsp;will be selected</small>
      </div>
    </template>
  </v-select>
</template>