Skip to content

Commit 2c492a6

Browse files
authored
Select search update
1 parent cc5034c commit 2c492a6

File tree

2 files changed

+85
-23
lines changed

2 files changed

+85
-23
lines changed

input/Select.vue

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
<template>
22
<div class="input-group">
33
<label v-if="label" :for="name">{{ label }} <slot></slot></label>
4-
<div class="custom-select" @blur="open = false" :tabindex="tabindex">
5-
<div class="selected" :class="{ open: open, inactive: inactive }" @click="open = !open">{{ selected }} <IconChevronDown class="selected-icon" /></div>
6-
<div class="rounded" :class="{ selectHide: !open }">
7-
<div ref="items" class="items">
8-
<div :key="0" @click="updateClick(null)">{{ placeholder }}</div>
9-
<div v-for="(option, i) of options" :key="i" @click="updateClick(option)" :class="{ highlight: check(option, modelValue) }">{{ option.value ?? option }} <IconCheckmark v-if="check(option, modelValue)" class="checkmark" /></div>
4+
<div :class="{ 'custom-select': true, 'custom-select-open': open }" :data-uid="uid" @blur="open = false" @click.stop="openSelect">
5+
<div class="selected" :class="{ open: open, inactive: inactive }">{{ selected }} <IconChevronDown class="selected-icon" /></div>
6+
<div class="rounded">
7+
<input type="text" placeholder="Search" @click.stop="" @keyup="filterOptions" />
8+
<div ref="items" class="items" :tabindex="tabindex">
9+
<div v-if="search_check" class="select-search-error">{{ searchError }}</div>
10+
<div v-if="!search_check" :key="0" @click.stop="updateClick(null)">{{ placeholder }}</div>
11+
<div v-for="(option, i) of filtered_options" :key="i" @click.stop="updateClick(option)" :class="{ highlight: check(option, modelValue) }">{{ option.value ?? option }} <IconCheckmark v-if="check(option, modelValue)" class="checkmark" /></div>
1012
</div>
1113
</div>
1214
<input ref="input" type="hidden" v-model="modelValue" :name="name" />
@@ -27,12 +29,29 @@ const props = defineProps({
2729
modelValue: { type: String },
2830
tabindex: { type: Number, default: 0 },
2931
placeholder: { type: String, default: 'Choose' },
32+
searchError: { type: String, default: 'Option does not exists.' },
3033
})
3134
const { label, name, options, modelValue, tabindex, placeholder } = toRefs(props)
3235
const input = ref(null)
3336
const selected = ref(null)
3437
const inactive = ref(false)
3538
const open = ref(false)
39+
const search_check = ref(false)
40+
const filtered_options = ref(options.value)
41+
const uid = ref('custom-select-' + Date.now())
42+
43+
function openSelect() {
44+
let all = document.querySelectorAll('.custom-select-open')
45+
all.forEach((el) => {
46+
let data = el.dataset.uid ?? null
47+
console.log(data)
48+
if (data != uid.value) {
49+
el.click()
50+
}
51+
})
52+
53+
open.value = !open.value
54+
}
3655
3756
// Test option highligt
3857
function check(option, modelValue) {
@@ -53,21 +72,25 @@ onMounted(() => {
5372
inactive.value = true
5473
modelValue.value = null
5574
}
75+
76+
document.addEventListener('click', (e) => {
77+
let a = document.querySelectorAll('.custom-select-open')
78+
a.forEach((el) => el.click())
79+
})
5680
})
5781
5882
function updateClick(option = null) {
5983
if (option == null) {
6084
modelValue.value = null
6185
selected.value = placeholder.value
6286
inactive.value = true
63-
open.value = false
6487
} else {
6588
modelValue.value = option.key ?? option
6689
selected.value = option.value ?? option
6790
inactive.value = false
68-
open.value = false
6991
}
70-
emit('update:modelValue', modelValue.value)
92+
open.value = false
93+
emit('update:modelValue', modelValue)
7194
}
7295
7396
function renameKeys(obj = { id: '1', name: 'Alex' }, newKeys = { id: 'key', name: 'value' }) {
@@ -77,6 +100,17 @@ function renameKeys(obj = { id: '1', name: 'Alex' }, newKeys = { id: 'key', name
77100
})
78101
return Object.assign({}, ...keyValues)
79102
}
103+
104+
function filterOptions(e) {
105+
filtered_options.value = options?.value?.filter((o) => {
106+
if (o?.value) {
107+
return o.value.toLowerCase().startsWith(e.target.value.toLowerCase())
108+
} else {
109+
return o.toLowerCase().startsWith(e.target.value.toLowerCase())
110+
}
111+
})
112+
search_check.value = filtered_options.value.length == 0 ? true : false
113+
}
80114
</script>
81115
82116
<style>

input/SelectPrefix.vue

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<template>
22
<div class="input-group">
33
<label v-if="label" :for="name">{{ label }} <slot></slot></label>
4-
<div class="custom-select" @blur="open = false" :tabindex="tabindex">
5-
<div class="selected" :class="{ open: open, inactive: inactive }" @click="open = !open">{{ selected }} <IconChevronDown class="selected-icon" /></div>
6-
<div class="rounded" :class="{ selectHide: !open }">
7-
<div ref="items" class="items">
8-
<div v-for="o of options" :key="o.prefix" :value="o.prefix" @click="updateClick(o)" :class="{ highlight: o.prefix == modelValue }">{{ o.name }} {{ o.emoji }} +{{ o.prefix }} <IconCheckmark v-if="o.prefix == modelValue" class="checkmark" /></div>
4+
<div :class="{ 'custom-select': true, 'custom-select-open': open }" :data-uid="uid" @blur="open = false" @click.stop="openSelect">
5+
<div class="selected" :class="{ open: open, inactive: inactive }">{{ selected }} <IconChevronDown class="selected-icon" /></div>
6+
<div class="rounded">
7+
<input type="text" placeholder="Search" @click.stop="" @keyup="filterOptions" />
8+
<div ref="items" class="items" :tabindex="tabindex">
9+
<div v-if="search_check" class="select-search-error">{{ searchError }}</div>
10+
<div v-for="(o, index) in filtered_options" :key="index" :value="o.prefix" @click.stop="updateClick(o)" :class="{ highlight: o.prefix == modelValue }">{{ o.name }} {{ o.emoji }} +{{ o.prefix }} <IconCheckmark v-if="o.prefix == modelValue" class="checkmark" /></div>
911
</div>
1012
</div>
1113
<input ref="input" type="hidden" v-model="modelValue" :name="name" />
@@ -25,22 +27,33 @@ const props = defineProps({
2527
name: { type: String },
2628
modelValue: { type: String },
2729
tabindex: { type: Number, default: 0 },
30+
searchError: { type: String, default: 'Option does not exists.' },
2831
})
29-
let { label, name, modelValue, tabindex } = toRefs(props)
32+
let { label, name, modelValue, tabindex, searchError } = toRefs(props)
3033
const input = ref(null)
3134
const selected = ref(null)
3235
const inactive = ref(false)
3336
const open = ref(false)
37+
const search_check = ref(false)
38+
const filtered_options = ref(options)
39+
const uid = ref('custom-select-' + Date.now())
3440
35-
function clear() {
36-
selected.value = `${options[0].emoji} +${options[0].prefix}`
37-
modelValue.value = options[0].prefix
38-
inactive.value = false
41+
function openSelect() {
42+
console.log('Select click')
43+
let all = document.querySelectorAll('.custom-select-open')
44+
all.forEach((el) => {
45+
let data = el.dataset.uid ?? null
46+
console.log(data)
47+
if (data != uid.value) {
48+
el.click()
49+
}
50+
})
51+
open.value = !open.value
3952
}
4053
4154
onMounted(() => {
4255
if (modelValue.value !== null) {
43-
let option = options?.find((option) => parseInt(option.prefix) === modelValue.value)
56+
let option = options?.find((o) => parseInt(o.prefix) === modelValue.value)
4457
if (option?.prefix) {
4558
selected.value = `${option.emoji} +${option.prefix}`
4659
} else {
@@ -49,19 +62,34 @@ onMounted(() => {
4962
} else {
5063
clear()
5164
}
65+
66+
document.addEventListener('click', (e) => {
67+
let a = document.querySelectorAll('.custom-select-open')
68+
a.forEach((el) => el.click())
69+
})
5270
})
5371
72+
function clear() {
73+
selected.value = `${options[0].emoji} +${options[0].prefix}`
74+
modelValue.value = options[0].prefix
75+
inactive.value = false
76+
}
77+
5478
function updateClick(option = null) {
5579
if (option == null) {
5680
clear()
57-
open.value = false
5881
} else {
5982
modelValue.value = option.prefix ?? null
6083
selected.value = `${option.emoji} +${option.prefix}`
6184
inactive.value = false
62-
open.value = false
6385
}
64-
emit('update:modelValue', modelValue.value)
86+
open.value = false
87+
emit('update:modelValue', modelValue)
88+
}
89+
90+
function filterOptions(e) {
91+
filtered_options.value = options.filter((o) => o.name.toLowerCase().startsWith(e.target.value.toLowerCase()))
92+
search_check.value = filtered_options.value.length == 0 ? true : false
6593
}
6694
</script>
6795

0 commit comments

Comments
 (0)