Select
Default
<RSelect />
is base component which will have <ROption />
as default slot. value of each item will be on value
prop of ROption
.
Custom Option
Default slot of ROption
components lets you render your custom item. by default only text
prop is shown. If you do not pass text
prop you need to use renderPlaceholder
to customize the placeholder and if select is multiple you should use custom selected items ( tags ) as well.
Custom Placeholder
If you don't specify text
on ROption
you need to use a custom placeholder which is a function accepting selected option( when single select ) or array of selected options( when multiple select ) and returns a string to be displayed when any item is selected. defaults to:
renderPlaceholder: (option: Option | Option[]) => {
if (Array.isArray(option)) return `${option.length} selected`
else return option.text || ''
}
Custom Selected Items
To show custom tags when selection is multiple you can use named slot of #selectedItem
which accepts option props. context
prop is used for passing custom data.
Custom Search
By default searchable
prop does search over text
prop of ROption
. If you don't pass text
or want a different type of searching you can use customSearch
prop which is a function and is called whenever the input changes accepting search query as it's parameter.
Async items
Here is an example of using items that are fetched from an api. noDropdownOnEmptySearch
hides dropdown when there is no search query.
v-model
is not empty ) but you don't have the list yet or values you have as initial modelValue are not on the list of your options, in this case you can use exposed method of setSelectedItems
to pass the items to RSelect. The first parameter is the array of objects as you would pass props to ROption
. this method does NOT modify
v-model
, it just updates selected items if there are any missing from options.<RSelect ref="selectRef">...</RSelect>
import { RSelect } from 'sevue'
const selectRef = ref<InstanceOf<typeof RSelect> | undefined>()
// letting rselect know of items that are selected but are not on options list:
selectRef.value.setSelectedItems([
{
value: item.id // mandatory
context: {} // to pass custom data you can later use for custom templating
}
])
RSelectGroup
Used when items are grouped.
Multiple
Initial value of v-model
or modelValue
needs to be an array. keepOpenAfterSelection
prevents the select from closing after value selection.
Disabled
This prop can be passed to RSelect
to disable the whole select or ROption
to disable specific option/options.
Optimized items
You might experience some lags when there are lots of items in your options list. You can optimize rendering of items using the method below:
You need to pass the main array of items to items
prop of RSelect
: <RSelect :items="myLongList" />
. doing so you get a prop in default slot of RSelect called optimizedItems
. you shall use this prop for rendering your list instead of myLongList
.
items array must have value
key in each item which is mandatory for setting values if not you can use itemExtractor
prop. it recieves item as it's first parameter and must return an object containing at least value
which will be used as value
prop for ROption
. this is equalant to passing props to ROption
.
<template>
<RSelect :items="myLongList" :itemExtractor="itemExtractor">
<template #default="{ optimizedItems }">
<ROption v-for="item in optimizedItems" :value="item.id" :text="item.title" />
</template>
</RSelect>
</template>
<script setup>
const itemExtractor = (item) => {
return {
...item,
value: item.id,
};
};
</script>
Controlling the optimized list
The list you receive as optimizedList
is being filtered based on a page state which is being increased each time user reaches end of the dropdown list. to customize the parameters you can use perPage
and paginationOffset
props. both are numbers and default to 10
(page) and 40
(paginationOffset)
Usage for grouped items
When you items are grouped ( for example Country[].City[]
) you can still use paginated list with same props described earlier plus you also need to speicfy itemsKey (default: 'items')
and groupIdentifier (default: 'id')
. itemsKey
is the key where the nested items are located and groupIdentifier
is the key to a property which is unique to each group. For example if we want to use in the following example as select items
[
{
title: "UK",
cities: [
{ name: "London", id: 1 }, { name: "Bristol", id: 2 }
],
},
{
title: "Russia",
cities: [
{ name: "Moscow", id: 3 }, { name: "Saint Petersburg", id: 4 }, { name: "Novosibirsk", id: 5 }
],
},
]
we should pass itemsKey="cities"
and groupIdentifier="title"
. so the result will look something like this:
<template>
<RSelect :items="myLongItems" groupIdentifier="title" itemsKey="cities" :itemExtractor="itemExtractor">
<template #default="{ optimizedItems }">
<ROption v-for="item in optimizedItems" :value="item.id" :text="item.title" />
</template>
</RSelect>
</template>
<script setup>
const myLongItems = ref([
{
title: "UK",
cities: [
{ name: "London", id: 1 }, { name: "Bristol", id: 2 }
],
},
{
title: "Russia",
cities: [
{ name: "Moscow", id: 3 }, { name: "Saint Petersburg", id: 4 }, { name: "Novosibirsk", id: 5 }
],
},
])
const itemExtractor = (item) => {
return {
...item,
value: item.id,
text: item.title
};
};
</script>
Creating Options
You can allow user to create new option. to do so you need to add canCreateOption
to RSelect
and use the newOption
prop which is a function that will be called whenever user has something typed on search input and pressed Enter. the type of function is
({newOption: string, isAlreadyInValue: boolean, isAlreadyInOptions: boolean}): Promise<boolean> | boolean
newOption
is what user has type in input.isAlreadyInValue
looks inmodelValue
for the typed string and is true if there is the same item onmodelValue
.isAlreadyInOptions
looks inoptions
state byvalue
key of each option and is true if there is any item.
Returning true closes the dropdown and resets search (if keepOpenAfterSelection
is false).
Using noDropdown
prop you can hide dropdown if it's only for making new items.
in order to handle new items you check if item is not already a selected value which means isAlreadyInValue
is false
and push new items to modelValue
( if it's multiple selection ).
you can push the newly create item to list of your options or use setSelectedItems
exposed method for updating selected values.
items
prop or have ROption
in the default slot unless noDropdown
is true
.const onNewOption = ({ newOption, isAlreadyInValue, isAlreadyInOptions }) => {
// 1. Update v-model
if (!isAlreadyInValue) {
selectedItems.value.push(newOption);
}
// 2. Update list of options
// if dropdown is hidden you can skip checking if there is already same item in list.
items.value.push({
text: newOption,
value: newOption,
});
// 2 alternative: You can also use exposed function of `setSelectedItems` if you do not care about the options. but you MUST make sure it's called after vModel is updated. for example using nextTick:
// nextTick(() => {
// selectRef.value.setSelectedItems([
// {
// value: newOption,
// text: newOption,
// },
// ]);
// });
// Should return a boolean to specify whether it was successfull or not
return true
};
items
prop or ROption
[]
[]
RSelect
itself and leaves the calculation of adding new items to developer is because it gives more flexibility to using the custom format on your v-model or list of options.State
Refer to Input State
Props
Name | Type | Required | Default Value | Description |
---|---|---|---|---|
searchable | boolean | No | false | If true, allows users to search for and select options from a dropdown menu. |
multiple | boolean | No | false | If true, allows users to select multiple options from the dropdown menu. |
modelValue | array | number | string | Yes | undefined | The selected value(s) of the dropdown menu. If multiple is set to true, an array of values is expected. |
placeholder | string | No | "" | The text displayed inside the dropdown menu when no options are selected. |
disabled | boolean | No | false | If true, disables the dropdown menu. |
label | string | No | undefined | The label displayed above the dropdown menu. |
keepOpenAfterSelection | boolean | No | false | If true, keeps the dropdown menu open after a selection has been made. |
color | string | No | undefined | The color of the Select. |
error | boolean | No | false | If true, adds error styling. |
message | string | No | undefined | The message displayed below the dropdown menu. |
inputProps | object of any | No | undefined | Props to pass down to input |
noDropdownOnEmptySearch | boolean | No | undefined | When search value is empty dropdown will not show (or hide of it is was open) |
noDropdown | boolean | No | undefined | whether do show a dropdown or not. can be usefull when user can create options by itself |
canCreateOption | boolean | No | undefined | if true, newOption will be visible as user starts typing on search field and newOption event will be emitted on click of new option or clicking enter |
loading | boolean | No | undefined | Loading state on select ( shows a spinner instead of chevron ) |
renderPlaceholder | (parameter: Option | Option[]) => string | No | Custom Placeholder | When some value is seleted this placeholder will be shown |
customSearch | (parameter: string) => void | No | undefined | called when input text changes. you can use this function to filter your items from an API or change search behaviour |
items | any[] | No | undefined | if provided will Optimized Items will be used |
itemsKey | string | No | 'items' | used for when using optimized items and list is nested ( grouped ) Usage for grouped items |
groupIdentifier | string | No | 'id' | used for when using optimized items and list is nested ( grouped ) Usage for grouped items |
paginationOffset | number | No | 40 | distance from bottom in pixels to trigger rendering new items |
perPage | number | No | 10 | number of items per page on optimized list |
itemExtractor | (parameter: any) => Option | No | undefined | used when format of item do not match the format of ROption props ( missing value ): Optimized Items |
dropdownClass | string | No | undefined | extra classes to pass down to dropdown ( since it's rendered on body you need to specify global styles for it. ) |
onNewOption | (arg0: { newOption: string; isAlreadyInValue: boolean; isAlreadyInOptions: boolean }) => Promise<boolean> | boolean | No | undefined | Used for adding new items ( tags ). if returns true dropdown will close and search input resets. otherwise both will stay |
popperOptions | - | No | undefined | extra options to pass to popper instance |
Events
Event | Arguments | Description |
---|---|---|
open | - | Called when dropdown opens. |
close | - | Called when dropdown closes. |
afterTransitionEnd | - | Called when dropdown close transition is done. |
search | - | Called search input value changes. |
Exposed
Name | value | description |
---|---|---|
setSelectedItems | (Option[]): void | Function for setting selected items (usefull when items are not available but there are some values selected) |
rInput | InstanceType\ | The input of RSelect (can be usefull for calling methods of RInput ). |
open | () => void | function for opening dropdown |
close | (resetSearch: boolean = true, blur: boolean = true) => void | function for closing dropdown |
resetSearch | () => void | function for clearing search input |
RSelect Slots
Name | slot props | description |
---|---|---|
default | {optimizedItems} | For rendering ROption or RSelectGroup . will have optimizedItems if :items prop is available |
selectedItem | { ...option, remove } | For rendering custom tags on multiple selection |
noItems | - | When there are no options |
before | - | before slot of RInput |
inputIcon | - | icon slot of RInput |
toggleIcon | {toggleOpen, active, loading} | custom toggle icon |
loadingSpinner | {loading} | custom loading spinner |
newOption | {addNewOption, search} | will be visible if canCreateOption is true and search is not empty. |
ROption Props
Name | Type | Required | Default Value | Description |
---|---|---|---|---|
value | string | number | Yes | 0 | Value of option. |
text | string | No | "" | Text of option. |
disabled | boolean | no | false | Whether item is disabled or not. |
color | string | no | undefined | Color of option. |
context | Record<string, any> | no | undefined | Any custom object to later be used. |
RSelectGroup Props
Name | Type | Required | Default Value | Description |
---|---|---|---|---|
title | string | No | undefined | Title of group |
keepTitleOnSearch | boolean | No | undefined | By default title hides when search input is not empty, if set to true you'd better hide it's options when there are no children available |
RSelectGroup Slots
Name | slot props | description |
---|---|---|
default | - | For rendering ROption s |
header | - | Header of group. ( will replace title and ignores both title and keepTitleOnSearch props ) |