Skip to content

Commit 7e974b5

Browse files
vratierbenjamincanac
andauthoredJul 18, 2024
feat(SelectMenu): handle function in showCreateOptionWhen prop (#1853)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
1 parent 6aaf12b commit 7e974b5

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<script setup lang="ts">
2+
const options = ref([
3+
{ id: 1, name: 'bug' },
4+
{ id: 2, name: 'documentation' },
5+
{ id: 3, name: 'duplicate' },
6+
{ id: 4, name: 'enhancement' },
7+
{ id: 5, name: 'good first issue' },
8+
{ id: 6, name: 'help wanted' },
9+
{ id: 7, name: 'invalid' },
10+
{ id: 8, name: 'question' },
11+
{ id: 9, name: 'wontfix' }
12+
])
13+
14+
const selected = ref([])
15+
16+
const labels = computed({
17+
get: () => selected.value,
18+
set: async (labels) => {
19+
const promises = labels.map(async (label) => {
20+
if (label.id) {
21+
return label
22+
}
23+
24+
// In a real app, you would make an API call to create the label
25+
const response = {
26+
id: options.value.length + 1,
27+
name: label.name
28+
}
29+
30+
options.value.push(response)
31+
32+
return response
33+
})
34+
35+
selected.value = await Promise.all(promises)
36+
}
37+
})
38+
39+
const showCreateOption = (query, results) => {
40+
const lowercaseQuery = String.prototype.toLowerCase.apply(query || '')
41+
return lowercaseQuery.length >= 3 && !results.find(option => {
42+
return String.prototype.toLowerCase.apply(option['name'] || '') === lowercaseQuery
43+
})
44+
}
45+
</script>
46+
47+
<template>
48+
<USelectMenu
49+
v-model="labels"
50+
by="id"
51+
name="labels"
52+
:options="options"
53+
option-attribute="name"
54+
multiple
55+
searchable
56+
creatable
57+
:show-create-option-when="showCreateOption"
58+
placeholder="Select labels"
59+
/>
60+
</template>

‎docs/content/2.components/select-menu.md

+12
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,18 @@ componentProps:
188188
---
189189
::
190190

191+
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.
192+
193+
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).
194+
195+
::component-example
196+
---
197+
component: 'select-menu-example-creatable-function'
198+
componentProps:
199+
class: 'w-full lg:w-48'
200+
---
201+
::
202+
191203
## Popper
192204

193205
Use the `popper` prop to customize the popper instance.

‎src/runtime/components/forms/SelectMenu.vue

+6-2
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ export default defineComponent({
265265
default: false
266266
},
267267
showCreateOptionWhen: {
268-
type: String as PropType<'always' | 'empty'>,
268+
type: [String, Function] as PropType<'always' | 'empty' | ((query: string, results: any[]) => boolean)>,
269269
default: () => configMenu.default.showCreateOptionWhen
270270
},
271271
placeholder: {
@@ -494,7 +494,11 @@ export default defineComponent({
494494
return null
495495
}
496496
}
497-
497+
if (typeof props.showCreateOptionWhen === 'function') {
498+
if (!props.showCreateOptionWhen(query.value, filteredOptions.value)) {
499+
return null
500+
}
501+
}
498502
return ['string', 'number'].includes(typeof props.modelValue) ? query.value : { [props.optionAttribute]: query.value }
499503
})
500504

0 commit comments

Comments
 (0)