2023-12-09 15:47:03 +01:00
|
|
|
<template>
|
2024-03-19 13:35:51 +01:00
|
|
|
<input-wrapper v-bind="inputWrapperProps">
|
2023-12-09 15:47:03 +01:00
|
|
|
<template #label>
|
|
|
|
|
<slot name="label" />
|
|
|
|
|
</template>
|
2024-05-16 14:50:40 +02:00
|
|
|
|
2024-04-15 19:39:03 +02:00
|
|
|
<v-select
|
|
|
|
|
v-model="compVal"
|
2024-05-16 14:50:40 +02:00
|
|
|
:dusk="name"
|
2024-04-15 19:39:03 +02:00
|
|
|
:data="finalOptions"
|
|
|
|
|
:label="label"
|
|
|
|
|
:option-key="optionKey"
|
|
|
|
|
:emit-key="emitKey"
|
|
|
|
|
:required="required"
|
|
|
|
|
:multiple="multiple"
|
2024-05-16 14:50:40 +02:00
|
|
|
:clearable="clearable"
|
2024-04-15 19:39:03 +02:00
|
|
|
:searchable="searchable"
|
|
|
|
|
:loading="loading"
|
|
|
|
|
:color="color"
|
|
|
|
|
:placeholder="placeholder"
|
|
|
|
|
:uppercase-labels="uppercaseLabels"
|
|
|
|
|
:theme="theme"
|
|
|
|
|
:has-error="hasError"
|
|
|
|
|
:allow-creation="allowCreation"
|
2024-05-16 14:50:40 +02:00
|
|
|
:disabled="disabled"
|
2024-04-15 19:39:03 +02:00
|
|
|
:help="help"
|
|
|
|
|
:help-position="helpPosition"
|
2024-05-16 14:50:40 +02:00
|
|
|
:remote="remote"
|
|
|
|
|
:dropdown-class="dropdownClass"
|
2024-04-15 19:39:03 +02:00
|
|
|
@update-options="updateOptions"
|
|
|
|
|
@update:model-value="updateModelValue"
|
|
|
|
|
>
|
2024-03-19 13:35:51 +01:00
|
|
|
<template #selected="{ option }">
|
2024-05-16 14:50:40 +02:00
|
|
|
<template v-if="multiple">
|
|
|
|
|
<div class="flex items-center truncate mr-6">
|
2024-06-27 17:52:49 +02:00
|
|
|
<span
|
|
|
|
|
class="truncate"
|
|
|
|
|
:class="[
|
|
|
|
|
theme.SelectInput.fontSize,
|
|
|
|
|
]"
|
|
|
|
|
>
|
2024-05-16 14:50:40 +02:00
|
|
|
{{ getOptionNames(selectedValues).join(', ') }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<template v-else>
|
|
|
|
|
<slot
|
|
|
|
|
name="selected"
|
|
|
|
|
:option="option"
|
|
|
|
|
:option-name="getOptionName(option)"
|
|
|
|
|
>
|
2023-12-09 15:47:03 +01:00
|
|
|
<div class="flex items-center truncate mr-6">
|
2024-06-27 17:52:49 +02:00
|
|
|
<div
|
|
|
|
|
:class="[
|
|
|
|
|
theme.SelectInput.fontSize,
|
|
|
|
|
]"
|
|
|
|
|
>
|
|
|
|
|
{{ getOptionName(option) }}
|
|
|
|
|
</div>
|
2023-12-09 15:47:03 +01:00
|
|
|
</div>
|
2024-05-16 14:50:40 +02:00
|
|
|
</slot>
|
|
|
|
|
</template>
|
2023-12-09 15:47:03 +01:00
|
|
|
</template>
|
2024-03-19 13:35:51 +01:00
|
|
|
<template #option="{ option, selected }">
|
2024-04-15 19:39:03 +02:00
|
|
|
<slot
|
|
|
|
|
name="option"
|
|
|
|
|
:option="option"
|
|
|
|
|
:selected="selected"
|
|
|
|
|
>
|
2024-05-16 14:50:40 +02:00
|
|
|
<span class="flex">
|
2024-06-27 17:52:49 +02:00
|
|
|
<p
|
|
|
|
|
class="flex-grow"
|
|
|
|
|
:class="[
|
|
|
|
|
theme.SelectInput.fontSize,
|
|
|
|
|
]"
|
|
|
|
|
>
|
2023-12-09 15:47:03 +01:00
|
|
|
{{ option.name }}
|
|
|
|
|
</p>
|
2024-04-15 19:39:03 +02:00
|
|
|
<span
|
|
|
|
|
v-if="selected"
|
|
|
|
|
class="absolute inset-y-0 right-0 flex items-center pr-4 dark:text-white"
|
|
|
|
|
>
|
2024-05-16 14:50:40 +02:00
|
|
|
<Icon
|
|
|
|
|
name="heroicons:check-16-solid"
|
|
|
|
|
class="w-5 h-5"
|
|
|
|
|
/>
|
2023-12-09 15:47:03 +01:00
|
|
|
</span>
|
|
|
|
|
</span>
|
|
|
|
|
</slot>
|
|
|
|
|
</template>
|
|
|
|
|
</v-select>
|
|
|
|
|
|
|
|
|
|
<template #help>
|
|
|
|
|
<slot name="help" />
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template #error>
|
|
|
|
|
<slot name="error" />
|
|
|
|
|
</template>
|
|
|
|
|
</input-wrapper>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
2024-06-27 17:52:49 +02:00
|
|
|
import {inputProps, useFormInput} from './useFormInput.js'
|
2024-05-16 14:50:40 +02:00
|
|
|
import InputWrapper from './components/InputWrapper.vue'
|
2023-12-09 15:47:03 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Options: {name,value} objects
|
|
|
|
|
*/
|
|
|
|
|
export default {
|
2024-05-16 14:50:40 +02:00
|
|
|
name: 'SelectInput',
|
2024-06-27 17:52:49 +02:00
|
|
|
components: {InputWrapper},
|
2023-12-09 15:47:03 +01:00
|
|
|
|
|
|
|
|
props: {
|
|
|
|
|
...inputProps,
|
2024-06-27 17:52:49 +02:00
|
|
|
options: {type: Array, required: true},
|
|
|
|
|
optionKey: {type: String, default: 'value'},
|
|
|
|
|
emitKey: {type: String, default: 'value'},
|
|
|
|
|
displayKey: {type: String, default: 'name'},
|
|
|
|
|
loading: {type: Boolean, default: false},
|
|
|
|
|
multiple: {type: Boolean, default: false},
|
|
|
|
|
searchable: {type: Boolean, default: false},
|
|
|
|
|
clearable: {type: Boolean, default: false},
|
|
|
|
|
allowCreation: {type: Boolean, default: false},
|
|
|
|
|
dropdownClass: {type: String, default: 'w-full'},
|
|
|
|
|
remote: {type: Function, default: null}
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
2024-06-27 17:52:49 +02:00
|
|
|
setup(props, context) {
|
2023-12-09 15:47:03 +01:00
|
|
|
return {
|
2024-05-16 14:50:40 +02:00
|
|
|
...useFormInput(props, context)
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
},
|
2024-06-27 17:52:49 +02:00
|
|
|
data() {
|
2023-12-09 15:47:03 +01:00
|
|
|
return {
|
2024-02-03 17:14:45 +01:00
|
|
|
additionalOptions: [],
|
2024-05-16 14:50:40 +02:00
|
|
|
selectedValues: []
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
2024-06-27 17:52:49 +02:00
|
|
|
finalOptions() {
|
2023-12-09 15:47:03 +01:00
|
|
|
return this.options.concat(this.additionalOptions)
|
2024-05-16 14:50:40 +02:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
compVal: {
|
2024-06-27 17:52:49 +02:00
|
|
|
handler(newVal, oldVal) {
|
2024-05-16 14:50:40 +02:00
|
|
|
if (!oldVal) {
|
|
|
|
|
this.handleCompValChanged()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
immediate: false
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-06-27 17:52:49 +02:00
|
|
|
mounted() {
|
2024-05-16 14:50:40 +02:00
|
|
|
this.handleCompValChanged()
|
2023-12-09 15:47:03 +01:00
|
|
|
},
|
|
|
|
|
methods: {
|
2024-06-27 17:52:49 +02:00
|
|
|
getOptionName(val) {
|
2023-12-09 15:47:03 +01:00
|
|
|
const option = this.finalOptions.find((optionCandidate) => {
|
|
|
|
|
return optionCandidate[this.optionKey] === val
|
|
|
|
|
})
|
|
|
|
|
if (option) return option[this.displayKey]
|
|
|
|
|
return null
|
|
|
|
|
},
|
2024-06-27 17:52:49 +02:00
|
|
|
getOptionNames(values) {
|
2024-05-16 14:50:40 +02:00
|
|
|
return values.map(val => {
|
2024-03-19 13:35:51 +01:00
|
|
|
return this.getOptionName(val)
|
|
|
|
|
})
|
|
|
|
|
},
|
2024-06-27 17:52:49 +02:00
|
|
|
updateModelValue(newValues) {
|
2024-02-10 12:46:17 +01:00
|
|
|
if (newValues === null) newValues = []
|
2024-02-03 17:14:45 +01:00
|
|
|
this.selectedValues = newValues
|
|
|
|
|
},
|
2024-06-27 17:52:49 +02:00
|
|
|
updateOptions(newItem) {
|
2023-12-09 15:47:03 +01:00
|
|
|
if (newItem) {
|
|
|
|
|
this.additionalOptions.push(newItem)
|
|
|
|
|
}
|
2024-04-15 19:39:03 +02:00
|
|
|
},
|
2024-06-27 17:52:49 +02:00
|
|
|
handleCompValChanged() {
|
2024-05-16 14:50:40 +02:00
|
|
|
if (this.compVal) {
|
|
|
|
|
this.selectedValues = this.compVal
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-09 15:47:03 +01:00
|
|
|
}
|
|
|
|
|
</script>
|