Bearbeiten
Verwenden Sie die v-model-Direktive, um den Wert der Listbox zu steuern, oder die default-value-Prop, um den Anfangswert festzulegen, wenn Sie den Zustand nicht steuern müssen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
},
{
label: 'Netherlands',
icon: 'i-lucide-map-pin',
value: 'NL'
},
{
label: 'Poland',
icon: 'i-lucide-map-pin',
value: 'PL'
},
{
label: 'Belgium',
icon: 'i-lucide-map-pin',
value: 'BE'
},
{
label: 'Portugal',
icon: 'i-lucide-map-pin',
value: 'PT'
},
{
label: 'Austria',
icon: 'i-lucide-map-pin',
value: 'AT'
},
{
label: 'Sweden',
icon: 'i-lucide-map-pin',
value: 'SE'
}
])
const value = ref({
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
})
</script>
<template>
<UListbox v-model="value" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
},
{
label: 'Netherlands',
icon: 'i-lucide-map-pin',
value: 'NL'
},
{
label: 'Poland',
icon: 'i-lucide-map-pin',
value: 'PL'
},
{
label: 'Belgium',
icon: 'i-lucide-map-pin',
value: 'BE'
},
{
label: 'Portugal',
icon: 'i-lucide-map-pin',
value: 'PT'
},
{
label: 'Austria',
icon: 'i-lucide-map-pin',
value: 'AT'
},
{
label: 'Sweden',
icon: 'i-lucide-map-pin',
value: 'SE'
}
])
const value = ref({
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
})
</script>
<template>
<UListbox v-model="value" :items="items" />
</template>Items Bearbeiten
Verwenden Sie die items-prop als Array von Objekten mit den folgenden Eigenschaften:
label?: string(nicht vorhanden)description?: stringtype?: "label" | "separator" | "item"074x[icon?: stringxph0777x#with-icon-in-items) |avatar?: AvatarPropschip?: ChipPropsdisabled?: boolean(nicht vorhanden)onSelect?: (e: Event) => void(nicht)class?: any(nicht)ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, ... }(nicht)
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox :items="items" />
</template>Sie können auch ein Array von Arrays an die items-Prop übergeben, um getrennte Gruppen von Elementen anzuzeigen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[][]>([
[
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
}
],
[
{
label: 'Brazil',
icon: 'i-lucide-map-pin',
value: 'BR'
},
{
label: 'Argentina',
icon: 'i-lucide-map-pin',
value: 'AR'
}
]
])
</script>
<template>
<UListbox :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[][]>([
[
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
}
],
[
{
label: 'Brazil',
icon: 'i-lucide-map-pin',
value: 'BR'
},
{
label: 'Argentina',
icon: 'i-lucide-map-pin',
value: 'AR'
}
]
])
</script>
<template>
<UListbox :items="items" />
</template>Mehrfach
Verwenden Sie die multiple-prop, um die Auswahl mehrerer Elemente zu ermöglichen. Wenn aktiviert, wird die v-model ein Array sein.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox multiple :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox multiple :items="items" />
</template>value Schlüsselwort
Sie können eine einzelne Eigenschaft des Objekts anstelle des gesamten Objekts binden, indem Sie die value-key-Prop verwenden.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<UListbox v-model="value" value-key="value" :items="items" class="w-full" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<UListbox v-model="value" value-key="value" :items="items" class="w-full" />
</template>Filter (englisch)
Verwenden Sie die filter-Prop, um eine Filtereingabe anzuzeigen, oder übergeben Sie ein Objekt, um die Input-Komponente anzupassen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
},
{
label: 'Netherlands',
icon: 'i-lucide-map-pin',
value: 'NL'
},
{
label: 'Poland',
icon: 'i-lucide-map-pin',
value: 'PL'
}
])
</script>
<template>
<UListbox :filter="{
placeholder: 'Filter...',
icon: 'i-lucide-search'
}" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
},
{
label: 'Netherlands',
icon: 'i-lucide-map-pin',
value: 'NL'
},
{
label: 'Poland',
icon: 'i-lucide-map-pin',
value: 'PL'
}
])
</script>
<template>
<UListbox :filter="{
placeholder: 'Filter...',
icon: 'i-lucide-search'
}" :items="items" />
</template>Selected Icon auswählen
Verwenden Sie die selected-icon prop, um das Symbol anzupassen, wenn ein Element ausgewählt ist. Standardmäßig i-lucide-check.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<UListbox v-model="value" selected-icon="i-lucide-flame" value-key="value" :items="items" class="w-full" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
const value = ref('FR')
</script>
<template>
<UListbox v-model="value" selected-icon="i-lucide-flame" value-key="value" :items="items" class="w-full" />
</template>x307xSize
Verwenden Sie die size-Prop, um die Größe der Listbox zu ändern.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox size="xl" :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox size="xl" :items="items" />
</template>Loading (englisch)
Verwenden Sie die loading-prop, um eine Ladeanzeige anzuzeigen. Verwenden Sie die loading-icon-prop, um das Symbol anzupassen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
}
])
</script>
<template>
<UListbox loading :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
}
])
</script>
<template>
<UListbox loading :items="items" />
</template>Disabled (englisch)
Verwenden Sie die disabled-Prop, um Benutzerinteraktionen mit der Listbox zu verhindern.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox disabled :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox disabled :items="items" />
</template>Examples Bearbeiten
With items type (Deutsche Übersetzung)
Sie können die type-Eigenschaft mit separator verwenden, um ein Trennzeichen zwischen Elementen anzuzeigen, oder label, um eine Beschriftung anzuzeigen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[][]>([
[
{
type: 'label',
label: 'Fruits'
},
{
label: 'Apple'
},
{
label: 'Banana'
},
{
label: 'Blueberry'
},
{
label: 'Grapes'
},
{
label: 'Pineapple'
}
],
[
{
type: 'label',
label: 'Vegetables'
},
{
label: 'Aubergine'
},
{
label: 'Broccoli'
},
{
label: 'Carrot'
},
{
label: 'Courgette'
},
{
label: 'Leek'
}
]
])
</script>
<template>
<UListbox :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[][]>([
[
{
type: 'label',
label: 'Fruits'
},
{
label: 'Apple'
},
{
label: 'Banana'
},
{
label: 'Blueberry'
},
{
label: 'Grapes'
},
{
label: 'Pineapple'
}
],
[
{
type: 'label',
label: 'Vegetables'
},
{
label: 'Aubergine'
},
{
label: 'Broccoli'
},
{
label: 'Carrot'
},
{
label: 'Courgette'
},
{
label: 'Leek'
}
]
])
</script>
<template>
<UListbox :items="items" />
</template>label-Elemente als Gruppenüberschriften verwenden, übergeben Sie ein Array von Arrays, damit ein Label bei der Suche zusammen mit seiner Gruppe herausgefiltert wird.With Icon in items (Deutsche Ausgabe)
Sie können die icon-Eigenschaft verwenden, um ein Icon innerhalb der Elemente anzuzeigen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'Backlog',
icon: 'i-lucide-circle-help',
value: 'backlog'
},
{
label: 'Todo',
icon: 'i-lucide-circle-plus',
value: 'todo'
},
{
label: 'In Progress',
icon: 'i-lucide-circle-arrow-up',
value: 'in_progress'
},
{
label: 'Done',
icon: 'i-lucide-circle-check',
value: 'done'
}
])
</script>
<template>
<UListbox :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'Backlog',
icon: 'i-lucide-circle-help',
value: 'backlog'
},
{
label: 'Todo',
icon: 'i-lucide-circle-plus',
value: 'todo'
},
{
label: 'In Progress',
icon: 'i-lucide-circle-arrow-up',
value: 'in_progress'
},
{
label: 'Done',
icon: 'i-lucide-circle-check',
value: 'done'
}
])
</script>
<template>
<UListbox :items="items" />
</template>With avatar in items (Mit Avatar in Elementen)
Sie können die avatar-Eigenschaft verwenden, um ein Avatar in den Elementen anzuzeigen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'benjamincanac',
avatar: {
src: 'https://github.com/benjamincanac.png'
}
},
{
label: 'HugoRCD',
avatar: {
src: 'https://github.com/HugoRCD.png'
}
},
{
label: 'atinux',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'romhml',
avatar: {
src: 'https://github.com/romhml.png'
}
}
])
</script>
<template>
<UListbox :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'benjamincanac',
avatar: {
src: 'https://github.com/benjamincanac.png'
}
},
{
label: 'HugoRCD',
avatar: {
src: 'https://github.com/HugoRCD.png'
}
},
{
label: 'atinux',
avatar: {
src: 'https://github.com/atinux.png'
}
},
{
label: 'romhml',
avatar: {
src: 'https://github.com/romhml.png'
}
}
])
</script>
<template>
<UListbox :items="items" />
</template>Mit Chip in den Gegenständen
Sie können die chip-Eigenschaft verwenden, um ein Chip in den Elementen anzuzeigen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'bug',
chip: {
color: 'error'
}
},
{
label: 'feature',
chip: {
color: 'success'
}
},
{
label: 'enhancement',
chip: {
color: 'info'
}
}
])
</script>
<template>
<UListbox :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'bug',
chip: {
color: 'error'
}
},
{
label: 'feature',
chip: {
color: 'success'
}
},
{
label: 'enhancement',
chip: {
color: 'info'
}
}
])
</script>
<template>
<UListbox :items="items" />
</template>With description in items (Beschreibung in Elementen)
Sie können die description-Eigenschaft verwenden, um zusätzlichen Text unterhalb der Beschriftung anzuzeigen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox :items="items" />
</template><script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items = ref<ListboxItem[]>([
{
label: 'France',
description: 'The Hexagon',
icon: 'i-lucide-map-pin',
value: 'FR'
},
{
label: 'Germany',
description: 'The Federal Republic',
icon: 'i-lucide-map-pin',
value: 'DE'
},
{
label: 'Italy',
description: 'The Boot',
icon: 'i-lucide-map-pin',
value: 'IT'
},
{
label: 'Spain',
description: 'The Bull Skin',
icon: 'i-lucide-map-pin',
value: 'ES'
}
])
</script>
<template>
<UListbox :items="items" />
</template>Control selected item (s) Ausgewähltes Element
Sie können das ausgewählte Element mit der default-value-prop-oder der v-model-Direktive steuern.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items: ListboxItem[] = [
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' }
]
const value = ref<ListboxItem>(items[2]!)
</script>
<template>
<UListbox
v-model="value"
:items="items"
class="w-full"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items: ListboxItem[] = [
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' }
]
const value = ref<ListboxItem>(items[2]!)
</script>
<template>
<UListbox
v-model="value"
:items="items"
class="w-full"
/>
</template>
Control Suchbegriff
Verwenden Sie die v-model:search-term-Direktive, um den Suchbegriff zu steuern.
<script setup lang="ts">
const searchTerm = ref('F')
const items = ref([
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' }
])
const value = ref()
</script>
<template>
<UListbox v-model="value" v-model:search-term="searchTerm" filter :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
const searchTerm = ref('F')
const items = ref([
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' }
])
const value = ref()
</script>
<template>
<UListbox v-model="value" v-model:search-term="searchTerm" filter :items="items" class="w-full" />
</template>
With ignore filter (Filter ignorieren)
Setzen Sie die ignore-filter prop auf true, um die interne Suche zu deaktivieren und Ihre eigene Suchlogik zu verwenden.
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'listbox-users-search',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({
label: user.name,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
}))
},
immediate: false
})
onMounted(() => {
execute()
})
</script>
<template>
<UListbox
v-model:search-term="searchTerm"
:items="users || []"
:filter="{
icon: 'i-lucide-search',
loading: status === 'pending'
}"
ignore-filter
class="w-full"
/>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { refDebounced } from '@vueuse/core'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'listbox-users-search',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({
label: user.name,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
}))
},
immediate: false
})
onMounted(() => {
execute()
})
</script>
<template>
<UListbox
v-model:search-term="searchTerm"
:items="users || []"
:filter="{
icon: 'i-lucide-search',
loading: status === 'pending'
}"
ignore-filter
class="w-full"
/>
</template>
refDebounced verwendet, um die API-Aufrufe zu entkräften.With Filterfelder
Verwenden Sie die filter-fields-Prop mit einem Array von Feldern, um nach. Defaults auf [labelKey] zu filtern.
<script setup lang="ts">
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users-email',
transform: (data: { id: number, name: string, email: string }[]) => {
return data?.map(user => ({
label: user.name,
email: user.email,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
}))
},
immediate: false
})
onMounted(() => {
execute()
})
</script>
<template>
<UListbox
:items="users || []"
:loading="status === 'pending'"
:filter-fields="['label', 'email']"
filter
class="w-full"
>
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
{{ item.email }}
</span>
</template>
</UListbox>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
const { data: users, status, execute } = await useLazyFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users-email',
transform: (data: { id: number, name: string, email: string }[]) => {
return data?.map(user => ({
label: user.name,
email: user.email,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}`, loading: 'lazy' as const }
}))
},
immediate: false
})
onMounted(() => {
execute()
})
</script>
<template>
<UListbox
:items="users || []"
:loading="status === 'pending'"
:filter-fields="['label', 'email']"
filter
class="w-full"
>
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
{{ item.email }}
</span>
</template>
</UListbox>
</template>
Mit Virtualisierung
Verwenden Sie die virtualize-Prop, um die Virtualisierung für große Listen als Boolean oder ein Objekt mit Optionen wie { estimateSize: 32, overscan: 12 } zu aktivieren.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items: ListboxItem[] = Array.from({ length: 1000 }, (_, i) => ({
label: `Item ${i + 1}`,
icon: 'i-lucide-file',
value: i + 1
}))
const value = ref<ListboxItem[]>([])
</script>
<template>
<UListbox
v-model="value"
:items="items"
multiple
virtualize
class="w-full"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items: ListboxItem[] = Array.from({ length: 1000 }, (_, i) => ({
label: `Item ${i + 1}`,
icon: 'i-lucide-file',
value: i + 1
}))
const value = ref<ListboxItem[]>([])
</script>
<template>
<UListbox
v-model="value"
:items="items"
multiple
virtualize
class="w-full"
/>
</template>
As eine Übertragungsliste
Sie können zwei Listbox-Komponenten mit Button-Steuerelementen zusammenstellen, um ein Übertragungslistenmuster zu erstellen.
<script setup lang="ts">
import type { ListboxItem } from '@nuxt/ui'
const items: ListboxItem[] = [
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' },
{ label: 'Belgium', icon: 'i-lucide-map-pin', value: 'BE' },
{ label: 'Portugal', icon: 'i-lucide-map-pin', value: 'PT' }
]
const targetItems = ref<ListboxItem[]>([])
const sourceSelection = ref<ListboxItem[]>([])
const targetSelection = ref<ListboxItem[]>([])
const sourceItems = computed(() => items.filter(item => !targetItems.value.some(t => t.value === item.value)))
function transferSelected() {
targetItems.value = [...targetItems.value, ...sourceSelection.value]
sourceSelection.value = []
}
function removeSelected() {
targetItems.value = targetItems.value.filter(item => !targetSelection.value.some(t => t.value === item.value))
targetSelection.value = []
}
</script>
<template>
<div class="flex items-stretch gap-4 w-full">
<div class="flex flex-col flex-1 gap-1">
<span class="text-sm font-medium text-highlighted">Available</span>
<UListbox
v-model="sourceSelection"
:items="sourceItems"
multiple
filter
class="size-full"
/>
</div>
<div class="flex flex-col items-center justify-center gap-1">
<UButton
icon="i-lucide-chevron-right"
color="neutral"
variant="outline"
:disabled="!sourceSelection.length"
@click="transferSelected"
/>
<UButton
icon="i-lucide-chevron-left"
color="neutral"
variant="outline"
:disabled="!targetSelection.length"
@click="removeSelected"
/>
</div>
<div class="flex flex-col flex-1 gap-1">
<span class="text-sm font-medium text-highlighted">Selected</span>
<UListbox
v-model="targetSelection"
:items="targetItems"
multiple
filter
class="size-full"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { ListboxItem } from '@nuxt/ui'
const items: ListboxItem[] = [
{ label: 'France', icon: 'i-lucide-map-pin', value: 'FR' },
{ label: 'Germany', icon: 'i-lucide-map-pin', value: 'DE' },
{ label: 'Italy', icon: 'i-lucide-map-pin', value: 'IT' },
{ label: 'Spain', icon: 'i-lucide-map-pin', value: 'ES' },
{ label: 'Netherlands', icon: 'i-lucide-map-pin', value: 'NL' },
{ label: 'Poland', icon: 'i-lucide-map-pin', value: 'PL' },
{ label: 'Belgium', icon: 'i-lucide-map-pin', value: 'BE' },
{ label: 'Portugal', icon: 'i-lucide-map-pin', value: 'PT' }
]
const targetItems = ref<ListboxItem[]>([])
const sourceSelection = ref<ListboxItem[]>([])
const targetSelection = ref<ListboxItem[]>([])
const sourceItems = computed(() => items.filter(item => !targetItems.value.some(t => t.value === item.value)))
function transferSelected() {
targetItems.value = [...targetItems.value, ...sourceSelection.value]
sourceSelection.value = []
}
function removeSelected() {
targetItems.value = targetItems.value.filter(item => !targetSelection.value.some(t => t.value === item.value))
targetSelection.value = []
}
</script>
<template>
<div class="flex items-stretch gap-4 w-full">
<div class="flex flex-col flex-1 gap-1">
<span class="text-sm font-medium text-highlighted">Available</span>
<UListbox
v-model="sourceSelection"
:items="sourceItems"
multiple
filter
class="size-full"
/>
</div>
<div class="flex flex-col items-center justify-center gap-1">
<UButton
icon="i-lucide-chevron-right"
color="neutral"
variant="outline"
:disabled="!sourceSelection.length"
@click="transferSelected"
/>
<UButton
icon="i-lucide-chevron-left"
color="neutral"
variant="outline"
:disabled="!targetSelection.length"
@click="removeSelected"
/>
</div>
<div class="flex flex-col flex-1 gap-1">
<span class="text-sm font-medium text-highlighted">Selected</span>
<UListbox
v-model="targetSelection"
:items="targetItems"
multiple
filter
class="size-full"
/>
</div>
</div>
</template>
API (englisch)
Props Bearbeiten
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
id | string | |
color | 'primary' | "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" |
size | 'md' | "sm" | "md" | "xs" | "lg" | "xl" |
items | TThe items to display in the list. | |
modelValue | _Number<_Optional<_Nullable<GetModelValue<T, VK, M, undefined>, Mod>, Mod>, Mod>The controlled value of the Listbox. Can be bound with | |
modelModifiers | Mod | |
defaultValue | _Number<_Optional<_Nullable<GetModelValue<T, VK, M, undefined>, Mod>, Mod>, Mod>The default value when not controlled. | |
multiple | false | MWhether multiple items can be selected. |
valueKey | undefined | VKWhen |
labelKey | 'label' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the label from the item. |
descriptionKey | 'description' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the description from the item. |
loading | boolean Whether the list is in a loading state. | |
loadingIcon | appConfig.ui.icons.loading | anyThe icon displayed when loading. |
filter | false | boolean | Omit<InputProps<AcceptableValue, ModelModifiers>, "modelValue" | "defaultValue"> Whether to display a filter input or not.
Can be an object to pass additional props to the input.
|
filterFields | [labelKey] | string[]The fields to filter by. |
ignoreFilter | false | boolean When |
selectedIcon | appConfig.ui.icons.check | anyThe icon displayed when an item is selected. |
virtualize | false | boolean | { overscan?: number ; estimateSize?: number | ((index: number) => number) | undefined; } | undefinedEnable virtualization for large lists. |
highlight | boolean Highlight the ring color like a focus state. | |
autofocus | boolean | |
autofocusDelay | 0 | number |
by | string | (a: AcceptableValue, b: AcceptableValue): booleanUse this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. | |
disabled | boolean When | |
highlightOnHover | true | boolean When |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
orientation | "vertical" | "horizontal"The orientation of the listbox. | |
required | boolean When | |
selectionBehavior | 'toggle' | "replace" | "toggle"How multiple selection should behave in the collection. |
searchTerm | '' | string |
ui | { root?: SlotClass; input?: SlotClass; content?: SlotClass; group?: SlotClass; label?: SlotClass; separator?: SlotClass; empty?: SlotClass; loading?: SlotClass; loadingIcon?: SlotClass; item?: SlotClass; itemLeadingIcon?: SlotClass; itemLeadingAvatar?: SlotClass; itemLeadingAvatarSize?: SlotClass; itemLeadingChip?: SlotClass; itemLeadingChipSize?: SlotClass; itemWrapper?: SlotClass; itemLabel?: SlotClass; itemDescription?: SlotClass; itemTrailing?: SlotClass; itemTrailingIcon?: SlotClass; } |
Slots Bearbeiten
| Slot | Type |
|---|---|
loading | {} |
empty | { searchTerm: string; } |
item | { item: NestedItem<T>; index: number; ui: object; } |
item-leading | { item: NestedItem<T>; index: number; ui: object; } |
item-label | { item: NestedItem<T>; index: number; } |
item-description | { item: NestedItem<T>; index: number; } |
item-trailing | { item: NestedItem<T>; index: number; ui: object; } |
Emits (englisch)
| Event | Type |
|---|---|
entryFocus | [event: CustomEvent<any>] |
highlight | [payload: { ref: HTMLElement; value: AcceptableValue; } | undefined] |
leave | [event: Event] |
change | [event: Event] |
update:modelValue | [value: _Number<_Optional<_Nullable<GetModelValue<T, VK, M, undefined>, Mod>, Mod>, Mod>] |
update:searchTerm | [value: string] |
Theme (englisch)
export default defineAppConfig({
ui: {
listbox: {
slots: {
root: 'flex flex-col min-h-0 min-w-0 ring ring-inset ring-default rounded-lg overflow-hidden',
input: 'border-b border-default',
content: 'relative overflow-y-auto flex-1 max-h-60 scroll-py-1 focus:outline-none',
group: 'p-1 isolate',
label: 'font-semibold text-highlighted',
separator: '-mx-1 my-1 h-px bg-border',
empty: 'text-center text-muted',
loading: 'flex items-center justify-center text-muted',
loadingIcon: 'animate-spin shrink-0',
item: [
'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-md data-disabled:cursor-not-allowed data-disabled:opacity-75 text-default data-highlighted:not-data-disabled:text-highlighted data-highlighted:not-data-disabled:before:bg-elevated/50',
'transition-colors before:transition-colors'
],
itemLeadingIcon: [
'shrink-0 text-dimmed group-data-highlighted:not-group-data-disabled:text-default',
'transition-colors'
],
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '',
itemLeadingChip: 'shrink-0',
itemLeadingChipSize: '',
itemWrapper: 'flex-1 flex flex-col min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate text-muted',
itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0'
},
variants: {
size: {
xs: {
label: 'p-1 text-[10px]/3 gap-1',
empty: 'py-3 text-xs',
loading: 'py-3',
loadingIcon: 'size-4',
item: 'p-1 text-xs gap-1',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4'
},
sm: {
label: 'p-1.5 text-[10px]/3 gap-1.5',
empty: 'py-4 text-xs',
loading: 'py-4',
loadingIcon: 'size-4',
item: 'p-1.5 text-xs gap-1.5',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4'
},
md: {
label: 'p-1.5 text-xs gap-1.5',
empty: 'py-6 text-sm',
loading: 'py-6',
loadingIcon: 'size-5',
item: 'p-1.5 text-sm gap-1.5',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5'
},
lg: {
label: 'p-2 text-xs gap-2',
empty: 'py-7 text-sm',
loading: 'py-7',
loadingIcon: 'size-5',
item: 'p-2 text-sm gap-2',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5'
},
xl: {
label: 'p-2 text-sm gap-2',
empty: 'py-8 text-base',
loading: 'py-8',
loadingIcon: 'size-6',
item: 'p-2 text-base gap-2',
itemLeadingIcon: 'size-6',
itemLeadingAvatarSize: 'xs',
itemLeadingChip: 'size-6',
itemLeadingChipSize: 'lg',
itemTrailingIcon: 'size-6',
itemDescription: 'text-sm'
}
},
color: {
primary: {
root: 'outline-primary/25 has-focus-visible:outline-3 has-focus-visible:ring-primary'
},
secondary: {
root: 'outline-secondary/25 has-focus-visible:outline-3 has-focus-visible:ring-secondary'
},
success: {
root: 'outline-success/25 has-focus-visible:outline-3 has-focus-visible:ring-success'
},
info: {
root: 'outline-info/25 has-focus-visible:outline-3 has-focus-visible:ring-info'
},
warning: {
root: 'outline-warning/25 has-focus-visible:outline-3 has-focus-visible:ring-warning'
},
error: {
root: 'outline-error/25 has-focus-visible:outline-3 has-focus-visible:ring-error'
},
neutral: {
root: 'outline-inverted/25 has-focus-visible:outline-3 has-focus-visible:ring-inverted'
}
},
virtualize: {
true: {
content: 'p-1 isolate'
},
false: {
content: 'divide-y divide-default'
}
},
disabled: {
true: {
root: 'opacity-75 cursor-not-allowed'
}
},
highlight: {
true: ''
}
},
compoundVariants: [
{
color: 'primary',
highlight: true,
class: {
root: 'ring ring-inset ring-primary'
}
},
{
color: 'neutral',
highlight: true,
class: {
root: 'ring ring-inset ring-inverted'
}
}
],
defaultVariants: {
color: 'primary',
size: 'md'
}
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
listbox: {
slots: {
root: 'flex flex-col min-h-0 min-w-0 ring ring-inset ring-default rounded-lg overflow-hidden',
input: 'border-b border-default',
content: 'relative overflow-y-auto flex-1 max-h-60 scroll-py-1 focus:outline-none',
group: 'p-1 isolate',
label: 'font-semibold text-highlighted',
separator: '-mx-1 my-1 h-px bg-border',
empty: 'text-center text-muted',
loading: 'flex items-center justify-center text-muted',
loadingIcon: 'animate-spin shrink-0',
item: [
'group relative w-full flex items-start select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-md data-disabled:cursor-not-allowed data-disabled:opacity-75 text-default data-highlighted:not-data-disabled:text-highlighted data-highlighted:not-data-disabled:before:bg-elevated/50',
'transition-colors before:transition-colors'
],
itemLeadingIcon: [
'shrink-0 text-dimmed group-data-highlighted:not-group-data-disabled:text-default',
'transition-colors'
],
itemLeadingAvatar: 'shrink-0',
itemLeadingAvatarSize: '',
itemLeadingChip: 'shrink-0',
itemLeadingChipSize: '',
itemWrapper: 'flex-1 flex flex-col min-w-0',
itemLabel: 'truncate',
itemDescription: 'truncate text-muted',
itemTrailing: 'ms-auto inline-flex gap-1.5 items-center',
itemTrailingIcon: 'shrink-0'
},
variants: {
size: {
xs: {
label: 'p-1 text-[10px]/3 gap-1',
empty: 'py-3 text-xs',
loading: 'py-3',
loadingIcon: 'size-4',
item: 'p-1 text-xs gap-1',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4'
},
sm: {
label: 'p-1.5 text-[10px]/3 gap-1.5',
empty: 'py-4 text-xs',
loading: 'py-4',
loadingIcon: 'size-4',
item: 'p-1.5 text-xs gap-1.5',
itemLeadingIcon: 'size-4',
itemLeadingAvatarSize: '3xs',
itemLeadingChip: 'size-4',
itemLeadingChipSize: 'sm',
itemTrailingIcon: 'size-4'
},
md: {
label: 'p-1.5 text-xs gap-1.5',
empty: 'py-6 text-sm',
loading: 'py-6',
loadingIcon: 'size-5',
item: 'p-1.5 text-sm gap-1.5',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5'
},
lg: {
label: 'p-2 text-xs gap-2',
empty: 'py-7 text-sm',
loading: 'py-7',
loadingIcon: 'size-5',
item: 'p-2 text-sm gap-2',
itemLeadingIcon: 'size-5',
itemLeadingAvatarSize: '2xs',
itemLeadingChip: 'size-5',
itemLeadingChipSize: 'md',
itemTrailingIcon: 'size-5'
},
xl: {
label: 'p-2 text-sm gap-2',
empty: 'py-8 text-base',
loading: 'py-8',
loadingIcon: 'size-6',
item: 'p-2 text-base gap-2',
itemLeadingIcon: 'size-6',
itemLeadingAvatarSize: 'xs',
itemLeadingChip: 'size-6',
itemLeadingChipSize: 'lg',
itemTrailingIcon: 'size-6',
itemDescription: 'text-sm'
}
},
color: {
primary: {
root: 'outline-primary/25 has-focus-visible:outline-3 has-focus-visible:ring-primary'
},
secondary: {
root: 'outline-secondary/25 has-focus-visible:outline-3 has-focus-visible:ring-secondary'
},
success: {
root: 'outline-success/25 has-focus-visible:outline-3 has-focus-visible:ring-success'
},
info: {
root: 'outline-info/25 has-focus-visible:outline-3 has-focus-visible:ring-info'
},
warning: {
root: 'outline-warning/25 has-focus-visible:outline-3 has-focus-visible:ring-warning'
},
error: {
root: 'outline-error/25 has-focus-visible:outline-3 has-focus-visible:ring-error'
},
neutral: {
root: 'outline-inverted/25 has-focus-visible:outline-3 has-focus-visible:ring-inverted'
}
},
virtualize: {
true: {
content: 'p-1 isolate'
},
false: {
content: 'divide-y divide-default'
}
},
disabled: {
true: {
root: 'opacity-75 cursor-not-allowed'
}
},
highlight: {
true: ''
}
},
compoundVariants: [
{
color: 'primary',
highlight: true,
class: {
root: 'ring ring-inset ring-primary'
}
},
{
color: 'neutral',
highlight: true,
class: {
root: 'ring ring-inset ring-inverted'
}
}
],
defaultVariants: {
color: 'primary',
size: 'md'
}
}
}
})
]
})