Skip to content

Commit

Permalink
feat(SelectMenu): handle function in showCreateOptionWhen prop (#1853)
Browse files Browse the repository at this point in the history
Co-authored-by: Benjamin Canac <[email protected]>
  • Loading branch information
vratier and benjamincanac authored Jul 18, 2024
1 parent 6aaf12b commit 7e974b5
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script setup lang="ts">
const options = ref([
{ id: 1, name: 'bug' },
{ id: 2, name: 'documentation' },
{ id: 3, name: 'duplicate' },
{ id: 4, name: 'enhancement' },
{ id: 5, name: 'good first issue' },
{ id: 6, name: 'help wanted' },
{ id: 7, name: 'invalid' },
{ id: 8, name: 'question' },
{ id: 9, name: 'wontfix' }
])
const selected = ref([])
const labels = computed({
get: () => selected.value,
set: async (labels) => {
const promises = labels.map(async (label) => {
if (label.id) {
return label
}
// In a real app, you would make an API call to create the label
const response = {
id: options.value.length + 1,
name: label.name
}
options.value.push(response)
return response
})
selected.value = await Promise.all(promises)
}
})
const showCreateOption = (query, results) => {
const lowercaseQuery = String.prototype.toLowerCase.apply(query || '')
return lowercaseQuery.length >= 3 && !results.find(option => {
return String.prototype.toLowerCase.apply(option['name'] || '') === lowercaseQuery
})
}
</script>

<template>
<USelectMenu
v-model="labels"
by="id"
name="labels"
:options="options"
option-attribute="name"
multiple
searchable
creatable
:show-create-option-when="showCreateOption"
placeholder="Select labels"
/>
</template>
12 changes: 12 additions & 0 deletions docs/content/2.components/select-menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,18 @@ componentProps:
---
::

Pass a function to the `show-create-option-when` prop to control wether or not to show the create option. This function takes two arguments: the query (as the first argument) and an array of current results (as the second argument). It should return true to display the create option.

The example below shows how to make the create option visible when the query is at least three characters long and does not exactly match any of the current results (case insensitive).

::component-example
---
component: 'select-menu-example-creatable-function'
componentProps:
class: 'w-full lg:w-48'
---
::

## Popper

Use the `popper` prop to customize the popper instance.
Expand Down
8 changes: 6 additions & 2 deletions src/runtime/components/forms/SelectMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export default defineComponent({
default: false
},
showCreateOptionWhen: {
type: String as PropType<'always' | 'empty'>,
type: [String, Function] as PropType<'always' | 'empty' | ((query: string, results: any[]) => boolean)>,
default: () => configMenu.default.showCreateOptionWhen
},
placeholder: {
Expand Down Expand Up @@ -494,7 +494,11 @@ export default defineComponent({
return null
}
}
if (typeof props.showCreateOptionWhen === 'function') {
if (!props.showCreateOptionWhen(query.value, filteredOptions.value)) {
return null
}
}
return ['string', 'number'].includes(typeof props.modelValue) ? query.value : { [props.optionAttribute]: query.value }
})
Expand Down

0 comments on commit 7e974b5

Please sign in to comment.