df-select Component
df-select selects one or several values from static or loaded choices, and optionally accepts new values ("tags").
Basic Usage
Basic demo with a fixed options list:
Advanced Features
Choices loaded by fetchChoices, and icons:
Integration with DynamicForms
df-select bound to @dynamicforms/vue-forms fields:
{
"firstName": "John",
"lastName": "Doe",
"age": 30,
"active": true,
"country": "si"
}Features
- Binds a
@dynamicforms/vue-formselement, av-model, or neither - Single and multiple selection
- Choices loaded through
fetchChoices - Entry of new values (tagging)
- Icons in choices
- Chips for selected values. With
multipleandallowNull, chips that wrap onto more rows put the clear button above the menu arrow; the layout follows the field's width. - A
nullselection underallowNull - Search with filtering
Props
In addition to common props from InputBase, this component supports:
| Prop | Type | Default | Description |
|---|---|---|---|
| choices | SelectChoice[] | undefined | Static list of choice options |
| fetchChoices | (query?: any, idValue?: any) => Promise<SelectChoice[]> | undefined | Function to load choices dynamically |
| multiple | boolean | false | Whether multiple selection is allowed |
| allowTags | boolean | false | Whether custom values can be entered |
| allowNull | boolean | true | Whether null/empty selection is allowed. With false, an enabled select whose value is empty selects the first choice; a read-only or disabled one leaves the value as it is and selects the first choice once it is enabled |
Inherited Props
This component inherits all common props from InputBase, including:
control- DynamicForms field objectmodelValue- The selected value(s)label- Input labelhint- Hint text- And more...
SelectChoice Interface
Each choice implements this interface:
interface SelectChoice {
id: any; // Unique identifier/value for the option
text: any; // Display text
icon?: string; // Optional icon name (Ionicons format)
}Value Format
The value depends on multiple:
When
multiple: false(default):- Returns a single value (the
idof the selected option) - Returns
nullwhen nothing is selected
- Returns a single value (the
When
multiple: true:- Returns an array of values (the
ids of selected options) - Returns
nullwhen nothing is selected (not an empty array)
- Returns an array of values (the
Dynamic Option Loading
When using the fetchChoices prop instead of static choices, the component:
- Calls the function while the component is being set up, before it is mounted, in the browser only (see Server-side rendering)
- Calls the function when the user types in the search field
- Uses the search text as the query parameter
- Uses the ids of the value that no loaded choice covers as the idValue parameter - an array when
multipleis set, a single id otherwise. This happens while the component is being set up and whenever the value changes from outside the component, also when the field is read-only. With an empty value, the setup call passes the value itself (null) as idValue and expects the unfiltered choices back.
Until that call resolves, the value is unchanged, and no chip shows the ids. Once it has resolved, the value is reconciled against the loaded choices as with static choices: an id the call returned no choice for is dropped from the value (unless allowTags is set). A call that rejects is logged with console.error and leaves the loaded choices as they are.
const fetchChoices = async (query?: string, idValue?: any): Promise<SelectChoice[]> => {
// Simulate API call
const response = await apiCall('/api/options', { search: query, ids: idValue });
return response.data.map(item => ({
id: item.id,
text: item.name,
icon: item.icon
}));
};Events
In addition to the common events from InputBase:
update:modelValue- When the selected value(s) changeupdate:modelValueDisplay- Carries aSelectChoice[]holding the choices that match the current value. It is emitted whenever the value settles: once while the component is being set up (withfetchChoicesand a non-empty value, only once the choices for the value have been fetched), again when the initialfetchChoicescall resolves, and on every later change of the selection
Slots
Two slots are forwarded to the underlying v-autocomplete / v-combobox, with the slot props Vuetify passes:
append-innerprepend-inner
Examples
Basic Single Selection
<template>
<df-select
v-model="selectedFruit"
:choices="fruits"
label="Choose a fruit"
/>
</template>
<script setup>
import { ref } from 'vue';
import { DfSelect } from '@dynamicforms/vuetify-inputs';
const selectedFruit = ref('apple');
const fruits = [
{ id: 'apple', text: 'Apple' },
{ id: 'banana', text: 'Banana' },
{ id: 'cherry', text: 'Cherry' }
];
</script>Multiple Selection with DynamicForms
<template>
<df-select
:control="form.fields.categories"
:choices="categories"
:multiple="true"
label="Select categories"
/>
</template>
<script setup>
import { Group, Field, ValidationError, Validators } from '@dynamicforms/vue-forms';
import { DfSelect } from '@dynamicforms/vuetify-inputs';
const categories = [
{ id: 1, text: 'Electronics', icon: 'flash-outline' },
{ id: 2, text: 'Books', icon: 'book-outline' },
{ id: 3, text: 'Clothing', icon: 'shirt-outline' }
];
const form = new Group({
categories: new Field({
value: [1],
validators: [
new Validators.Validator((value) => {
if (!value || value.length === 0) return [new ValidationError('no_category', {}, 'Select at least one category')];
return null;
})
]
})
});
</script>