2023-05-03 18:37:14 +08:00
|
|
|
<template>
|
2023-05-03 19:39:10 +08:00
|
|
|
<Select class="sn-select--search" :options="currentOptions" :placeholder="placeholder" :disabled="disabled" @change="change" @blur="blur" @open="open" @close="close">
|
2023-05-03 18:37:14 +08:00
|
|
|
<input ref="focusElement" v-model="query" type="text" class="sn-select__search-input" :placeholder="searchPlaceholder" />
|
|
|
|
<span class="sn-select__value">{{ valueLabel || (placeholder || i18n.t('general.select')) }}</span>
|
|
|
|
<span class="sn-select__caret caret"></span>
|
|
|
|
</Select>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import Select from './select.vue'
|
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'SelectSearch',
|
|
|
|
props: {
|
|
|
|
options: { type: Array, default: () => [] },
|
|
|
|
optionsUrl: { type: String },
|
|
|
|
placeholder: { type: String },
|
2023-05-03 19:39:10 +08:00
|
|
|
searchPlaceholder: { type: String },
|
|
|
|
disabled: { type: Boolean }
|
2023-05-03 18:37:14 +08:00
|
|
|
},
|
|
|
|
components: { Select },
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
value: null,
|
|
|
|
query: null,
|
|
|
|
currentOptions: null,
|
|
|
|
isOpen: false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
created() {
|
|
|
|
this.currentOptions = this.options;
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
query() {
|
|
|
|
if(!this.query) {
|
|
|
|
this.currentOptions = this.options;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.optionsUrl) {
|
|
|
|
this.fetchOptions();
|
|
|
|
} else {
|
|
|
|
this.currentOptions = this.options.filter((o) => o[1].toLowerCase().includes(this.query.toLowerCase()));
|
|
|
|
}
|
2023-05-05 16:31:35 +08:00
|
|
|
},
|
|
|
|
options() {
|
|
|
|
this.currentOptions = this.options;
|
2023-05-03 18:37:14 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
valueLabel() {
|
2023-05-05 16:31:35 +08:00
|
|
|
let option = this.currentOptions.find((o) => o[0] === this.value);
|
2023-05-03 18:37:14 +08:00
|
|
|
return option && option[1];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
blur() {
|
2023-05-05 16:31:35 +08:00
|
|
|
this.isOpen = false;
|
2023-05-03 18:37:14 +08:00
|
|
|
this.$emit('blur');
|
|
|
|
},
|
|
|
|
change(value) {
|
|
|
|
this.value = value;
|
2023-05-03 19:39:10 +08:00
|
|
|
this.isOpen = false;
|
2023-05-03 18:37:14 +08:00
|
|
|
this.$emit('change', this.value);
|
|
|
|
},
|
|
|
|
open() {
|
|
|
|
this.isOpen = true;
|
|
|
|
this.$emit('open');
|
|
|
|
},
|
|
|
|
close() {
|
|
|
|
this.isOpen = false;
|
|
|
|
this.$emit('close');
|
|
|
|
},
|
|
|
|
fetchOptions() {
|
2023-05-05 16:31:35 +08:00
|
|
|
$.get(`${this.optionsUrl}?query=${this.query || ''}`,
|
2023-05-03 18:37:14 +08:00
|
|
|
(data) => {
|
|
|
|
this.currentOptions = data;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|