Skip to content

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:

Basic example
Selected value: cherry

Advanced Features ​

Choices loaded by fetchChoices, and icons:

Dynamic options loading
Selected value:

Integration with DynamicForms ​

df-select bound to @dynamicforms/vue-forms fields:

Person Form
Form Output
{
  "firstName": "John",
  "lastName": "Doe",
  "age": 30,
  "active": true,
  "country": "si"
}

Features ​

  • Binds a @dynamicforms/vue-forms element, a v-model, or neither
  • Single and multiple selection
  • Choices loaded through fetchChoices
  • Entry of new values (tagging)
  • Icons in choices
  • Chips for selected values. With multiple and allowNull, chips that wrap onto more rows put the clear button above the menu arrow; the layout follows the field's width.
  • A null selection under allowNull
  • Search with filtering

Props ​

In addition to common props from InputBase, this component supports:

PropTypeDefaultDescription
choicesSelectChoice[]undefinedStatic list of choice options
fetchChoices(query?: any, idValue?: any) => Promise<SelectChoice[]>undefinedFunction to load choices dynamically
multiplebooleanfalseWhether multiple selection is allowed
allowTagsbooleanfalseWhether custom values can be entered
allowNullbooleantrueWhether 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 object
  • modelValue - The selected value(s)
  • label - Input label
  • hint - Hint text
  • And more...

SelectChoice Interface ​

Each choice implements this interface:

typescript
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 id of the selected option)
    • Returns null when nothing is selected
  • When multiple: true:

    • Returns an array of values (the ids of selected options)
    • Returns null when nothing is selected (not an empty array)

Dynamic Option Loading ​

When using the fetchChoices prop instead of static choices, the component:

  1. Calls the function while the component is being set up, before it is mounted, in the browser only (see Server-side rendering)
  2. Calls the function when the user types in the search field
  3. Uses the search text as the query parameter
  4. Uses the ids of the value that no loaded choice covers as the idValue parameter - an array when multiple is 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.

typescript
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) change
  • update:modelValueDisplay - Carries a SelectChoice[] holding the choices that match the current value. It is emitted whenever the value settles: once while the component is being set up (with fetchChoices and a non-empty value, only once the choices for the value have been fetched), again when the initial fetchChoices call 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-inner
  • prepend-inner

Examples ​

Basic Single Selection ​

vue
<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 ​

vue
<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>

Released under the MIT License.