Skip to content

Commit

Permalink
feat(BaseListbox): allow value prop as model with v-model.prop (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnCampionJr committed Aug 14, 2023
1 parent ddb76f5 commit 908e585
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 4 deletions.
63 changes: 63 additions & 0 deletions .playground/pages/tests/form/listbox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<script setup lang="ts">
definePageMeta({
title: 'Listbox',
icon: 'ic:round-menu-open',
description:
'Test use of both objects and object value props in listbox models',
section: 'form',
})
const frameworks = [
{ label: 'React', value: 'react' },
{ label: 'Vue', value: 'vue' },
{ label: 'Angular', value: 'angular' },
{ label: 'Svelte', value: 'svelte' },
]
const model = ref({
frameworkId: '',
framework: {},
})
const properties = {
value: 'value',
label: 'label',
}
</script>

<template>
<div
class="flex flex-col gap-12 [&>*]:p-8 [&>:nth-child(odd)]:bg-muted-100 dark:[&>:nth-child(odd)]:bg-muted-900 pb-32"
>
<div>
<BaseHeading size="xl" weight="medium" class="mb-10">
Default Listbox
</BaseHeading>
<div class="grid grid-cols-3 gap-4">
<BaseListbox
v-model="model.framework"
:items="frameworks"
:properties="properties"
/>
<pre> {{ model }}</pre>
<BaseButton @click="model.framework = frameworks[1]">
Set Framework to Vue
</BaseButton>
</div>
</div>

<div>
<BaseHeading size="xl" weight="medium" class="mb-10">
Listbox with Object Key
</BaseHeading>
<div class="grid grid-cols-3 gap-4">
<BaseListbox
v-model.prop="model.frameworkId"
:items="frameworks"
:properties="properties"
/>
<pre> {{ model }}</pre>
<BaseButton @click="model.frameworkId = 'vue'">
Set Framework to Vue
</BaseButton>
</div>
</div>
</div>
</template>
33 changes: 29 additions & 4 deletions components/form/BaseListbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,21 @@ const props = withDefaults(
/**
* The model value of the multiselect.
*
* @modifiers
* `v-model="value"`
*
* @modifiers
* the value property of an object (as defined in properties.value) rather than the object itself
* `v-model.prop="value"`
*/
modelValue?: any
/**
* Used internaly to allow v-model.number and v-model.trim
*/
modelModifiers?: any
/**
* The shape of the multiselect.
*/
Expand Down Expand Up @@ -117,6 +129,7 @@ const props = withDefaults(
{
icon: '',
modelValue: undefined,
modelModifiers: () => ({}),
selectedIcon: 'lucide:check',
label: '',
placeholder: '',
Expand Down Expand Up @@ -167,7 +180,7 @@ const contrastStyle = {
'muted-contrast': 'nui-listbox-muted-contrast',
}
const value = useVModel(props, 'modelValue', emits, {
const vmodel = useVModel(props, 'modelValue', emits, {
passive: true,
})
Expand All @@ -181,6 +194,14 @@ const placeholder = computed(() => {
return props.placeholder
})
const value = computed(() => {
if (props.modelModifiers.prop && props.properties.value) {
const attr = props.properties.value
return props.items.find((i) => i[attr] === props.modelValue)
}
return props.modelValue
})
</script>

<template>
Expand All @@ -198,8 +219,8 @@ const placeholder = computed(() => {
>
<Listbox
v-slot="{ open }: { open: boolean }"
v-model="value"
:by="props.properties.value"
v-model="vmodel"
:by="props.modelModifiers.prop ? undefined : props.properties.value"
:multiple="props.multiple"
:disabled="props.disabled"
>
Expand Down Expand Up @@ -316,7 +337,11 @@ const placeholder = computed(() => {
:key="
props.properties.value ? item[props.properties.value] : item
"
:value="item"
:value="
props.modelModifiers.prop && props.properties.value
? item[props.properties.value]
: item
"
as="template"
>
<li
Expand Down

0 comments on commit 908e585

Please sign in to comment.