Dropdown
Dropdowns appears when the user interacts with a trigger element (such as a button or a link) and is usually used for navigation menus, form selections, actions, and filters.
Basic Usage
Dropdowns are versatile UI components that can be integrated with various elements, such as buttons, chips, inputs, and more, to provide users with a list of options or actions.
<template>
<spr-dropdown
id="sample-dropdown"
v-model="dropdownModel"
:menu-list="menuList"
@update:model-value="handleSelectedItem"
>
<spr-input v-model="inputTextModel" label="Dropdown Label" readonly placeholder="Select item..." />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const dropdownModel = ref([]);
const inputTextModel = ref('');
const menuList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' },
{ text: 'Date', value: 'date' },
{ text: 'Elderberry', value: 'elderberry' },
{ text: 'Fig', value: 'fig' },
{ text: 'Grape', value: 'grape' },
{ text: 'Nectarine', value: 'nectarine' },
{ text: 'Orange', value: 'orange' },
{ text: 'Papaya', value: 'papaya' },
{ text: '89 Quince', value: '50' },
]);
const handleSelectedItem = (selectedItem) => {
inputTextModel.value[inputModel] = menuList.value.find((item) => item.value === selectedItem[0]).text;
};
</script>
Multi Select
This feature allows users to select multiple options from the dropdown list. It provides a more flexible way of choosing several items without closing the dropdown. Just pass the prop multi-select
.
<template>
<spr-dropdown
id="sample-dropdown"
v-model="dropdownModel"
:menu-list="menuList"
multi-select
@update:model-value="handleSelectedItem"
>
<spr-input v-model="inputTextModel" label="Dropdown Label" readonly placeholder="Select item..." />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const dropdownModel = ref([]);
const inputTextModel = ref('');
const menuList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' },
{ text: 'Date', value: 'date' },
{ text: 'Elderberry', value: 'elderberry' },
{ text: 'Fig', value: 'fig' },
{ text: 'Grape', value: 'grape' },
{ text: 'Nectarine', value: 'nectarine' },
{ text: 'Orange', value: 'orange' },
{ text: 'Papaya', value: 'papaya' },
{ text: '89 Quince', value: '50' },
]);
const handleSelectedItem = (selectedItem) => {
const selectedTexts = selectedItem
.map((item) => menuList.value.find((menuItem) => menuItem.value === item).text)
.join(', ');
inputTextModel.value[inputModel] = selectedTexts;
};
</script>
Multiple Number Values
The dropdown component fully supports arrays of number values in multi-select mode, preserving the numeric type throughout the selection process.
Multiple Number Values Demo
Selected values: None
Current selection type:
undefined
Current selection:
[]<template>
<spr-dropdown
id="number-multi-dropdown"
v-model="selectedNumbers"
:menu-list="numberOptions"
multi-select
@update:model-value="handleSelectedItems"
>
<spr-input
v-model="displayText"
label="Select Numbers"
readonly
placeholder="Select numbers..."
/>
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
// Define number options with numeric values
const numberOptions = [
{ text: 'One', value: 1 },
{ text: 'Two', value: 2 },
{ text: 'Three', value: 3 },
{ text: 'Four', value: 4 },
{ text: 'Five', value: 5 }
];
// Initialize with preselected values
const selectedNumbers = ref([1, 3]); // Selected "One" and "Three"
const displayText = ref('One, Three');
// Handle selected items
const handleSelectedItems = (items) => {
// Numbers are preserved in the items array
const selectedTexts = items.map(value => {
const option = numberOptions.find(opt => opt.value === value);
return option ? option.text : '';
}).filter(Boolean).join(', ');
// Update display text
displayText.value = selectedTexts;
};
</script>
Key Points About Number Value Support
- Value Type Preservation: Number values remain as numbers in the v-model
- Type-Safe Comparison: Both direct number comparison and string representation comparison are supported
- Pre-Selected Values: You can pre-select number values using an array of numbers
- Mixed Types: While supported, we recommend using consistent types (all strings or all numbers) for better maintainability
For more details and advanced examples, see Dropdown Number Multi-Select Example.
Grouped Items By
You can group items by default
, A-Z
or Z-A
order by passing the group-items-by
prop and specifying the desired grouping type. See List: Grouped Items for more examples.
<template>
<div class="spr-grid spr-gap-4">
<spr-dropdown
id="sample-dropdown1"
v-model="dropdownModel.inputText3"
:menu-list="menuList"
group-items-by="A-Z"
@update:model-value="handleSingleSelectedItem"
>
<spr-input v-model="inputTextModel" label="Single Select Dropdown" readonly placeholder="Select item..." />
</spr-dropdown>
<spr-dropdown
id="sample-dropdown2"
v-model="dropdownModel.inputText4"
:menu-list="menuList"
group-items-by="A-Z"
multi-select
@update:model-value="handleSelectedItem"
>
<spr-input v-model="inputTextModel" label="Multi Select Dropdown" readonly placeholder="Select item..." />
</spr-dropdown>
</div>
</template>
Pre-Selected Items
Pre-selected items are options that are automatically selected when the dropdown is first displayed. You can achieve this by adding the value
as an array of strings to the v-model
.
<template>
<div class="spr-grid spr-gap-4">
<spr-dropdown
id="dropdownSample1"
v-model="dropdownModel.dropdownModel1"
:menu-list="menuList"
group-items-by="A-Z"
@update:model-value="(value) => handleSelectedItem(value, 'single', 'inputText5')"
>
<spr-input
v-model="inputTextModel.inputTextModel1"
label="Single Select Dropdown"
readonly
placeholder="Select item..."
/>
</spr-dropdown>
<spr-dropdown
id="dropdownSample26"
v-model="dropdownModel.dropdownModel2"
:menu-list="menuList"
multi-select
group-items-by="A-Z"
@update:model-value="(value) => handleSelectedItem(value, 'multi', 'inputText6')"
>
<spr-input
v-model="inputTextModel.inputTextModel2"
label="Multi Select Dropdown"
readonly
placeholder="Select item..."
/>
</spr-dropdown>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
const dropdownModel = ref({
dropdownModel1: ['apple'],
dropdownModel2: ['date', 'fig', 'orange'],
});
const inputTextModel = ref({
inputTextModel1: '',
inputTextModel2: '',
});
// Load selected values to input texts
onMounted(() => {
handleSelectedItem(dropdownModel.value.dropdownModel1, 'single', 'inputTextModel1');
handleSelectedItem(dropdownModel.value.dropdownModel2, 'multi', 'inputTextModel2');
});
const handleSelectedItem = (selectedItem, dropdownType, inputModel) => {
if (dropdownType === 'single') {
inputTextModel.value[inputModel] = menuList.value.find((item) => item.value === selectedItem[0]).text;
}
if (dropdownType === 'multi') {
const selectedTexts = selectedItem
.map((item) => menuList.value.find((menuItem) => menuItem.value === item).text)
.join(', ');
inputTextModel.value[inputModel] = selectedTexts;
}
};
</script>
Placements
Placement refers to where the dropdown popper will be positioned relative to its trigger element (e.g., button, input field). Pass the placement
props to modify the placement of the dropdown popper.
The available placement options are: auto
, auto-start
, auto-end
, top
, top-start
, top-end
, right
, right-start
, right-end
, bottom
, bottom-start
, bottom-end
, left
, left-start
, and left-end
.
The default placement is bottom
.
Search
The search feature allows users to quickly filter and find specific items within the dropdown list by typing in a search query. Pass down the string text
of the item with the prop search-string
.
<template>
<spr-dropdown
id="sample-dropdown"
v-model="dropdownModel.sampleDropdown"
:menu-list="menuList"
:search-string="inputTextModel"
@update:model-value="handleSelectedItem"
>
<spr-input v-model="inputTextModel" label="Dropdown Label" placeholder="Select item..." />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputTextModel = ref('');
const dropdownModel = ref('');
const menuList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' },
{ text: 'Date', value: 'date' },
{ text: 'Elderberry', value: 'elderberry' },
{ text: 'Fig', value: 'fig' },
{ text: 'Grape', value: 'grape' },
{ text: 'Nectarine', value: 'nectarine' },
{ text: 'Orange', value: 'orange' },
{ text: 'Papaya', value: 'papaya' },
{ text: '89 Quince', value: '50' },
]);
const handleSelectedItem = (selectedItem) => {
inputTextModel.value[inputModel] = menuList.value.find((item) => item.value === selectedItem[0]).text;
};
</script>
Width and Popper Width
You can modify the width of the dropdown component in two ways: by adjusting the width of the dropdown wrapper or by changing the width of the dropdown popper.
Width
- Is the overall width wrapper of both parent element and popper element.
Popper Width
- Width of only popper element
<template>
<spr-dropdown
id="sample-dropdown"
:menu-list="menuList"
width="50%"
popper-width="200px"
@update:model-value="handleSelectedItem"
>
<spr-input v-model="inputTextModel" label="Dropdown Label" placeholder="Select item..." readonly />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputTextModel = ref('');
const menuList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' },
{ text: 'Date', value: 'date' },
{ text: 'Elderberry', value: 'elderberry' },
{ text: 'Fig', value: 'fig' },
{ text: 'Grape', value: 'grape' },
{ text: 'Nectarine', value: 'nectarine' },
{ text: 'Orange', value: 'orange' },
{ text: 'Papaya', value: 'papaya' },
{ text: '89 Quince', value: '50' },
]);
const handleSelectedItem = (selectedItem) => {
inputTextModel.value = menuList.value.find((item) => item.value === selectedItem[0]).text;
};
</script>
Other Components Integration
Dropdowns can be integrated with various UI components like buttons, inputs, and chips. This allows for seamless interaction with other parts of the interface, ensuring consistency and enhancing user experience across the application.
<template>
<div class="spr-grid spr-gap-4">
<spr-dropdown id="sample-dropdown1" :menu-list="menuList" width="200px" popper-width="200px">
<spr-button tone="success">Dropdown</spr-button>
</spr-dropdown>
<spr-dropdown id="sample-dropdown2" :menu-list="menuList" width="200px" popper-width="200px">
<spr-chips label="Basic Chip" />
</spr-dropdown>
<spr-dropdown id="sample-dropdown3" :menu-list="menuList" width="200px" popper-width="200px">
<spr-lozenge label="Plain" />
</spr-dropdown>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const menuList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' },
{ text: 'Date', value: 'date' },
{ text: 'Elderberry', value: 'elderberry' },
{ text: 'Fig', value: 'fig' },
{ text: 'Grape', value: 'grape' },
{ text: 'Nectarine', value: 'nectarine' },
{ text: 'Orange', value: 'orange' },
{ text: 'Papaya', value: 'papaya' },
{ text: '89 Quince', value: '50' },
]);
</script>
Popper Strategy
The Popper strategy is primarily used when working with elements like modal. It helps control the positioning behavior of popper. The strategy ensures that the popper element is dynamically positioned based on the viewport, the reference element, or other factors such as scrolling or resizing.
By default, the Popper strategy is set to absolute
, which positions the popper element relative to the nearest positioned ancestor (usually the body element). However, you can change the strategy
to fixed
, which positions the popper element relative to the viewport, ensuring that it remains in place even when the page is scrolled.
Pass the prop popper-strategy
to change the behavior position of the popper.
Important to note:
Do not forget to pass prop wrapperPosition
to overwrite relative
position into initial
.
<template>
<spr-button tone="success" @click="modalModel = true">Open Modal</spr-button>
<spr-modal v-model="modalModel" title="Dropdown with Modal">
<spr-dropdown
id="sample-dropdown"
v-model="dropdownModel"
:menu-list="menuList"
wrapper-position="initial"
popper-stategy="fixed"
@update:model-value="handleSelectedItem"
>
<spr-input v-model="inputTextModel" label="Dropdown Label" placeholder="Select item..." readonly />
</spr-dropdown>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
</p>
</spr-modal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const dropdownModel = ref([]);
const inputTextModel = ref('');
const modalModel = ref(false);
const menuList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' },
{ text: 'Date', value: 'date' },
{ text: 'Elderberry', value: 'elderberry' },
{ text: 'Fig', value: 'fig' },
{ text: 'Grape', value: 'grape' },
{ text: 'Nectarine', value: 'nectarine' },
{ text: 'Orange', value: 'orange' },
{ text: 'Papaya', value: 'papaya' },
{ text: '89 Quince', value: '50' },
]);
const handleSelectedItem = (selectedItem) => {
inputTextModel.value[inputModel] = menuList.value.find((item) => item.value === selectedItem[0]).text;
};
</script>
Infinite Scroll
Infinite scroll allows the dropdown list to load more items as the user scrolls, this feature is particularly for back-end api integration. Instead of loading the entire list at once, new items are dynamically added as needed, improving performance and usability. Pass @infinite-scroll-trigger
emit to get the trigger of menu when it reaches bottom.
Paginated Menu List - Should load 10 Items per page:
Pagination:
{ "totalpages": 10, "currentPage": 1 }
Data:
[ { "text": "Apple", "value": "apple" }, { "text": "Banana", "value": "banana" }, { "text": "Cherry", "value": "cherry" }, { "text": "Date", "value": "date" }, { "text": "Elderberry", "value": "elderberry" }, { "text": "Fig", "value": "fig" }, { "text": "Grape", "value": "grape" }, { "text": "Honeydew", "value": "honeydew" }, { "text": "Indian Fig", "value": "indian_fig" }, { "text": "Jackfruit", "value": "jackfruit" } ]<template>
<spr-dropdown id="sample-dropdown" :menu-list="menuList" @infinite-scroll-trigger="handleInfiniteScrollTrigger">
<spr-input v-model="inputTextModel" label="Dropdown Label" placeholder="Select item..." readonly />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const inputTextModel = ref('');
const modalModel = ref(false);
const menuList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' },
{ text: 'Date', value: 'date' },
{ text: 'Elderberry', value: 'elderberry' },
{ text: 'Fig', value: 'fig' },
{ text: 'Grape', value: 'grape' },
{ text: 'Nectarine', value: 'nectarine' },
{ text: 'Orange', value: 'orange' },
{ text: 'Papaya', value: 'papaya' },
{ text: '89 Quince', value: '50' },
]);
const APIisLoading = ref(false);
const pagination = ref({
totalpages: 10,
currentPage: 1,
});
const handleInfiniteScrollTrigger = () => {
if (pagination.value.currentPage === pagination.value.totalpages || APIisLoading.value) return;
APIisLoading.value = true;
pagination.value.currentPage += 1;
getGhibliFilms();
};
const getGhibliFilms = async () => {
try {
const response = await fetch('https://ghibliapi.vercel.app/films');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const options = await response.json();
paginatedMenuList.value = options.length
? [
...(paginatedMenuList.value || []),
...options.map((option: { id: string; original_title_romanised: string }) => ({
text: option.original_title_romanised,
value: option.id.replace(/\s+/g, ''),
})),
]
: [];
APIisLoading.value = false;
} catch (error) {
console.error('There was a problem with the fetch operation:', error);
}
};
</script>
Ladderized Dropdown
Ladderized dropdown utilizes the Ladderized List component to display the dropdown items in a hierarchical manner. The v-model
prop is an array of strings representing order of selected items per level.
<template>
<div>
<spr-dropdown
id="dropdown28"
:menu-list="mockDropdownData"
v-model="dropdownModel"
:ladderized="true"
@update:model-value="handleLadderizedDropdown"
>
<spr-input v-model="inputTextModel" label="Ladderized Dropdown" placeholder="Select item..." />
</spr-dropdown>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const dropdownModel = ref([]);
const inputTextModel = ref('');
const mockDropdownData = [
{
text: 'Lion',
value: 'lion',
subtext: 'King of the jungle',
sublevel: [
{
text: 'Cub',
value: 'cub',
subtext: 'Young lion',
sublevel: [
{
text: 'Cub 1',
value: 'cub1',
},
{
text: 'Cub 2',
value: 'cub2',
},
],
},
{
text: 'Pride Member',
value: 'pride-member',
subtext: 'Member of a lion pride',
},
],
},
{
text: 'Elephant',
value: 'elephant',
subtext: 'Largest land animal',
sublevel: [
{
text: 'Calf',
value: 'calf',
subtext: 'Young elephant',
},
],
},
{
text: 'Giraffe',
value: 'giraffe',
subtext: 'Tallest living terrestrial animal',
sublevel: [
{
text: 'Calf',
value: 'giraffe-calf',
subtext: 'Young giraffe',
},
{
text: 'Adult',
value: 'giraffe-adult',
subtext: 'Mature giraffe',
},
],
},
{
text: 'Zebra',
value: 'zebra',
subtext: 'Known for distinctive black and white stripes',
sublevel: [
{
text: 'Foal',
value: 'zebra-foal',
subtext: 'Young zebra',
},
{
text: 'Mare',
value: 'zebra-mare',
subtext: 'Adult female zebra',
},
],
},
];
const handleLadderizedDropdown = (value) => {
let tempValue: string[] = [];
let tempMenuList: MenuListType[] = mockDropdownData;
value.forEach((item) => {
const activeItem = tempMenuList.find((listItem) => item === listItem.value);
if (activeItem) {
tempValue.push(activeItem.text);
if (activeItem.sublevel) {
tempMenuList = activeItem.sublevel;
}
}
});
inputTextModel.value.inputText28 = tempValue.join(', ');
};
</script>
Ladderized Dropdown Search
Ladderized dropdown search allows users to filter items in a hierarchical manner. This feature is particularly useful when dealing with large datasets, as it enables users to quickly locate specific items within nested structures. Can be used if the ladderized
prop is set to true
and searchString
prop has a value.
LIMITATION
Ladderized dropdown search does not support multi-select and can only search through two hierarchical levels (root level and sublevel).
<template>
<div>
<spr-dropdown
id="dropdown28"
:menu-list="mockDropdownData"
v-model="dropdownModel"
:ladderized="true"
:search-string="inputTextModel"
@update:model-value="handleLadderizedDropdown"
>
<spr-input v-model="inputTextModel" label="Ladderized Dropdown" placeholder="Select item..." />
</spr-dropdown>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const dropdownModel = ref([]);
const inputTextModel = ref('');
const mockDropdownData = [
{
text: 'Lion',
value: 'lion',
subtext: 'King of the jungle',
sublevel: [
{
text: 'Cub',
value: 'cub',
subtext: 'Young lion',
sublevel: [
//cannot be searched
{
text: 'Cub 1',
value: 'cub1',
},
{
text: 'Cub 2',
value: 'cub2',
},
],
},
{
text: 'Pride Member',
value: 'pride-member',
subtext: 'Member of a lion pride',
},
],
},
{
text: 'Elephant',
value: 'elephant',
subtext: 'Largest land animal',
sublevel: [
{
text: 'Calf',
value: 'calf',
subtext: 'Young elephant',
},
],
},
{
text: 'Giraffe',
value: 'giraffe',
subtext: 'Tallest living terrestrial animal',
sublevel: [
{
text: 'Calf',
value: 'giraffe-calf',
subtext: 'Young giraffe',
},
{
text: 'Adult',
value: 'giraffe-adult',
subtext: 'Mature giraffe',
},
],
},
{
text: 'Zebra',
value: 'zebra',
subtext: 'Known for distinctive black and white stripes',
sublevel: [
{
text: 'Foal',
value: 'zebra-foal',
subtext: 'Young zebra',
},
{
text: 'Mare',
value: 'zebra-mare',
subtext: 'Adult female zebra',
},
],
},
];
const handleLadderizedDropdown = (value) => {
let tempValue: string[] = [];
let tempMenuList: MenuListType[] = mockDropdownData;
value.forEach((item) => {
const activeItem = tempMenuList.find((listItem) => item === listItem.value);
if (activeItem) {
tempValue.push(activeItem.text);
if (activeItem.sublevel) {
tempMenuList = activeItem.sublevel;
}
}
});
inputTextModel.value = tempValue.join(', ');
};
</script>
Disabled, Active & Readonly
This is only applicable to selected components, such as form input fields. You can learn more in the Input Form.
To disable the popper from showing when the wrapper is clicked, pass the disabled prop.
Supported Value Types
The dropdown component supports various types of values for both single and multi-selection. The v-model
binding can accept different data formats depending on your needs.
Single Primitive Values
For single selection of primitive types like strings or numbers:
Value: apple
Value: 42
<template>
<spr-dropdown
id="string-dropdown"
v-model="stringValue"
:menu-list="stringMenuList"
@update:model-value="handleStringSelection"
>
<spr-input v-model="stringDisplay" label="String Selection" readonly placeholder="Select a fruit..." />
</spr-dropdown>
<spr-dropdown
id="number-dropdown"
v-model="numberValue"
:menu-list="numberMenuList"
@update:model-value="handleNumberSelection"
>
<spr-input v-model="numberDisplay" label="Number Selection" readonly placeholder="Select a number..." />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
// For string values
const stringValue = ref('apple'); // Single string value
const stringDisplay = ref('Apple');
// For number values
const numberValue = ref(42); // Single number value
const numberDisplay = ref('42');
const stringMenuList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' }
]);
const numberMenuList = ref([
{ text: '42', value: 42 },
{ text: '100', value: 100 },
{ text: '200', value: 200 }
]);
const handleStringSelection = () => {
const selected = stringMenuList.value.find(item => item.value === stringValue.value);
stringDisplay.value = selected ? selected.text : '';
};
const handleNumberSelection = () => {
const selected = numberMenuList.value.find(item => item.value === numberValue.value);
numberDisplay.value = selected ? selected.text : '';
};
</script>
Single Object Values
For single selection of full objects:
Value: { "id": 1, "name": "John", "role": "Developer" }
<template>
<spr-dropdown
id="object-dropdown"
v-model="selectedUser"
:menu-list="userList"
text-field="name" <!-- Specify which field to display as text -->
value-field="id" <!-- Specify which field to use as value -->
@update:model-value="handleUserSelection"
>
<spr-input v-model="userDisplay" label="User Selection" readonly placeholder="Select a user..." />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
// Object selection using full object reference
const selectedUser = ref({ id: 1, name: 'John', role: 'Developer' });
const userDisplay = ref('John');
const userList = ref([
{ id: 1, name: 'John', role: 'Developer' },
{ id: 2, name: 'Jane', role: 'Designer' },
{ id: 3, name: 'Bob', role: 'Manager' }
]);
const handleUserSelection = () => {
// When using full objects, the display value should be updated
userDisplay.value = selectedUser.value.name;
};
</script>
Multiple Primitive Values
For multi-selection of primitive types like strings or numbers:
Value: [ "apple", "banana" ] (Fruits)
Value: [ 1, 2, 3 ] (Numbers)
<template>
<spr-dropdown
id="multi-string-dropdown"
v-model="selectedFruits"
:menu-list="fruitList"
multi-select
@update:model-value="handleFruitsSelection"
>
<spr-input v-model="fruitsDisplay" label="Fruits Selection" readonly placeholder="Select fruits..." />
</spr-dropdown>
<spr-dropdown
id="multi-number-dropdown"
v-model="selectedNumbers"
:menu-list="numbersList"
multi-select
@update:model-value="handleNumbersSelection"
>
<spr-input v-model="numbersDisplay" label="Numbers Selection" readonly placeholder="Select numbers..." />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
// Multiple string values
const selectedFruits = ref(['apple', 'banana']); // Array of strings
const fruitsDisplay = ref('Apple, Banana');
// Multiple number values
const selectedNumbers = ref([1, 2, 3]); // Array of numbers
const numbersDisplay = ref('1, 2, 3');
const fruitList = ref([
{ text: 'Apple', value: 'apple' },
{ text: 'Banana', value: 'banana' },
{ text: 'Cherry', value: 'cherry' },
{ text: 'Date', value: 'date' },
]);
const numbersList = ref([
{ text: '1', value: 1 },
{ text: '2', value: 2 },
{ text: '3', value: 3 },
{ text: '4', value: 4 },
]);
const handleFruitsSelection = () => {
const selectedTexts = selectedFruits.value.map(value => {
const item = fruitList.value.find(fruit => fruit.value === value);
return item ? item.text : '';
});
fruitsDisplay.value = selectedTexts.filter(Boolean).join(', ');
};
const handleNumbersSelection = () => {
const selectedTexts = selectedNumbers.value.map(value => {
const item = numbersList.value.find(num => num.value === value);
return item ? item.text : '';
});
numbersDisplay.value = selectedTexts.filter(Boolean).join(', ');
};
</script>
Multiple Object Values
For multi-selection of full objects:
<template>
<spr-dropdown
id="multi-object-dropdown"
v-model="selectedUsers"
:menu-list="usersList"
text-field="name"
value-field="id"
multi-select
@update:model-value="handleUsersSelection"
>
<spr-input v-model="usersDisplay" label="Team Members" readonly placeholder="Select team members..." />
</spr-dropdown>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
// Multiple object values
const selectedUsers = ref([
{ id: 1, name: 'John', role: 'Developer' },
{ id: 2, name: 'Jane', role: 'Designer' }
]);
const usersDisplay = ref('John, Jane');
const usersList = ref([
{ id: 1, name: 'John', role: 'Developer' },
{ id: 2, name: 'Jane', role: 'Designer' },
{ id: 3, name: 'Bob', role: 'Manager' },
{ id: 4, name: 'Alice', role: 'Product Owner' }
]);
const handleUsersSelection = () => {
// When using full objects, extract the display names
const names = selectedUsers.value.map(user => user.name);
usersDisplay.value = names.join(', ');
};
</script>
API Reference
Name | Description | Type | Default |
---|---|---|---|
id | Required to bind popper within the datepicker | Array | - |
v-model | Value binding for the dropdown. Accepts:
| String | Number | Object | Array | [] |
menu-list | List of options composed of `text` and `value` properties | MenuListType[] (see List) | [] |
width | Defines the width of the dropdown component wrapper | String | `100%` |
popper-width | Defines the width of the dropdown's popper | String | `100%` |
popper-strategy | Defines how the dropdown's popper is positioned relative to the reference element. Can be `absolute` or `fixed` | string | `absolute` |
placement | Changes the placement of the dropdown popper (e.g., `bottom`, `top`, `left`, `right`) | string | `bottom` |
multi-select | If set, allows multiple selections in the dropdown | Boolean | false |
disabled | If set, allows to disabled popper on click to the wrapper | Boolean | false |
search-string | Search string to filter the dropdown list | String | - |
ladderized | If set, allows to display dropdown items in a hierarchical manner. | Boolean | false |
@get-popper-state | Event emitted when the popper state is changed (e.g., opened or closed) | Function | - |
@infinite-scroll-trigger | Event emitted when the dropdown is scrolled to the bottom. Useful for dynamic data loading | Function | - |
remove-current-level-in-back-label | Defines whether the back label in the ladderized list will exclude the current level | Boolean | false |