opnform-host-nginx/client/components/forms/SelectInput.vue

188 lines
4.6 KiB
Vue
Raw Normal View History

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>
<v-select
v-model="compVal"
:dusk="name"
:data="finalOptions"
:label="label"
:option-key="optionKey"
:emit-key="emitKey"
:required="required"
:multiple="multiple"
:clearable="clearable"
:searchable="searchable"
:loading="loading"
:color="color"
:placeholder="placeholder"
:uppercase-labels="uppercaseLabels"
:theme="theme"
:has-error="hasError"
:allow-creation="allowCreation"
:disabled="disabled"
:help="help"
:help-position="helpPosition"
:remote="remote"
:dropdown-class="dropdownClass"
@update-options="updateOptions"
@update:model-value="updateModelValue"
>
2024-03-19 13:35:51 +01:00
<template #selected="{ option }">
<template v-if="multiple">
<div class="flex items-center truncate mr-6">
<span
class="truncate"
:class="[
theme.SelectInput.fontSize,
]"
>
{{ 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">
<div
:class="[
theme.SelectInput.fontSize,
]"
>
{{ getOptionName(option) }}
</div>
2023-12-09 15:47:03 +01:00
</div>
</slot>
</template>
2023-12-09 15:47:03 +01:00
</template>
2024-03-19 13:35:51 +01:00
<template #option="{ option, selected }">
<slot
name="option"
:option="option"
:selected="selected"
>
<span class="flex">
<p
class="flex-grow"
:class="[
theme.SelectInput.fontSize,
]"
>
{{ getOptionName(option) }}
2023-12-09 15:47:03 +01:00
</p>
<span
v-if="selected"
class="absolute inset-y-0 right-0 flex items-center pr-4 dark:text-white"
>
<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>
import {inputProps, useFormInput} from './useFormInput.js'
import InputWrapper from './components/InputWrapper.vue'
2023-12-09 15:47:03 +01:00
/**
* Options: {name,value} objects
*/
export default {
name: 'SelectInput',
components: {InputWrapper},
2023-12-09 15:47:03 +01:00
props: {
...inputProps,
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
},
setup(props, context) {
2023-12-09 15:47:03 +01:00
return {
...useFormInput(props, context)
2023-12-09 15:47:03 +01:00
}
},
data() {
2023-12-09 15:47:03 +01:00
return {
additionalOptions: [],
selectedValues: []
2023-12-09 15:47:03 +01:00
}
},
computed: {
finalOptions() {
2023-12-09 15:47:03 +01:00
return this.options.concat(this.additionalOptions)
}
},
watch: {
compVal: {
handler(newVal, oldVal) {
if (!oldVal) {
this.handleCompValChanged()
}
},
immediate: false
}
},
mounted() {
this.handleCompValChanged()
2023-12-09 15:47:03 +01:00
},
methods: {
getOptionName(val) {
2023-12-09 15:47:03 +01:00
const option = this.finalOptions.find((optionCandidate) => {
return optionCandidate[this.optionKey] === val ||
(typeof val === 'object' && optionCandidate[this.optionKey] === val[this.optionKey])
2023-12-09 15:47:03 +01:00
})
if (option) return option[this.displayKey]
return null
},
getOptionNames(values) {
return values.map(val => {
2024-03-19 13:35:51 +01:00
return this.getOptionName(val)
})
},
updateModelValue(newValues) {
2024-02-10 12:46:17 +01:00
if (newValues === null) newValues = []
this.selectedValues = newValues
},
updateOptions(newItem) {
2023-12-09 15:47:03 +01:00
if (newItem) {
this.additionalOptions.push(newItem)
}
},
handleCompValChanged() {
if (this.compVal) {
this.selectedValues = this.compVal
}
}
}
2023-12-09 15:47:03 +01:00
}
</script>