Files
site/nova/resources/js/components/Form/SelectField.vue

147 lines
3.5 KiB
Vue
Executable File

<template>
<default-field :field="field" :errors="errors" :show-help-text="showHelpText">
<template slot="field">
<!-- Search Input -->
<search-input
v-if="!isReadonly && isSearchable"
@input="performSearch"
@clear="clearSelection"
@selected="selectOption"
:error="hasError"
:value="selectedOption"
:data="filteredOptions"
:clearable="field.nullable"
trackBy="value"
class="w-full"
>
<!-- The Selected Option Slot -->
<div slot="default" v-if="selectedOption" class="flex items-center">
{{ selectedOption.label }}
</div>
<!-- Options List Slot -->
<div
slot="option"
slot-scope="{ option, selected }"
class="flex items-center text-sm font-semibold leading-5 text-90"
:class="{ 'text-white': selected }"
>
{{ option.label }}
</div>
</search-input>
<!-- Select Input Field -->
<select-control
v-else
:id="field.attribute"
:dusk="field.attribute"
@change="handleChange"
:value="this.value"
class="w-full form-control form-select"
:class="errorClasses"
:options="field.options"
:disabled="isReadonly"
>
<option value="" selected :disabled="!field.nullable">
{{ placeholder }}
</option>
</select-control>
</template>
</default-field>
</template>
<script>
import { FormField, HandlesValidationErrors } from 'laravel-nova'
export default {
mixins: [HandlesValidationErrors, FormField],
data: () => ({
selectedOption: null,
search: '',
}),
created() {
if (this.field.value && this.isSearchable) {
this.selectedOption = _(this.field.options).find(
v => v.value == this.field.value
)
}
},
methods: {
/**
* Provide a function that fills a passed FormData object with the
* field's internal value attribute. Here we are forcing there to be a
* value sent to the server instead of the default behavior of
* `this.value || ''` to avoid loose-comparison issues if the keys
* are truthy or falsey
*/
fill(formData) {
formData.append(this.field.attribute, this.value)
},
/**
* Set the search string to be used to filter the select field.
*/
performSearch(event) {
this.search = event
},
/**
* Clear the current selection for the field.
*/
clearSelection() {
this.selectedOption = ''
this.value = ''
},
/**
* Select the given option.
*/
selectOption(option) {
this.selectedOption = option
this.value = option.value
},
/**
* Handle the selection change event.
*/
handleChange(e) {
this.value = e.target.value
if (this.field) {
Nova.$emit(this.field.attribute + '-change', this.value)
}
},
},
computed: {
/**
* Determine if the related resources is searchable
*/
isSearchable() {
return this.field.searchable
},
/**
* Return the field options filtered by the search string.
*/
filteredOptions() {
return this.field.options.filter(option => {
return (
option.label.toLowerCase().indexOf(this.search.toLowerCase()) > -1
)
})
},
/**
* Return the placeholder text for the field.
*/
placeholder() {
return this.field.placeholder || this.__('Choose an option')
},
},
}
</script>