Skip to content

Commit d81f47d

Browse files
committed
feat(field-select): custom select field component
1 parent e4cae6f commit d81f47d

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

src/fields/input/FieldSelect.vue

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<template>
2+
<div class="vfg-select">
3+
<span class="vfg-select-label" :class="{'text-muted': !selectedName}" @click.prevent="onClickInput">
4+
<template v-if="selectedName">{{ selectedName }}</template>
5+
<template v-else>{{ field.emptyText || 'Select an option' }}</template>
6+
<span style="float:right;">
7+
<!-- ChevronDown from https://heroicons.com -->
8+
<svg
9+
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
10+
stroke-width="1.5"
11+
stroke="currentColor" style="height: 15px;"
12+
>
13+
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
14+
</svg>
15+
</span>
16+
</span>
17+
<div v-if="isOpened" class="vfg-select-list-container">
18+
<div class="vfg-select-list">
19+
<div
20+
v-for="option in field.options"
21+
:key="option.value"
22+
class="vfg-select-option"
23+
:class="{'selected': currentModelValue === option.value}"
24+
@click.prevent="selectOption(option)"
25+
>
26+
{{ option.name }}
27+
</div>
28+
</div>
29+
</div>
30+
</div>
31+
</template>
32+
33+
<script>
34+
import { abstractField } from '@/mixins'
35+
36+
export default {
37+
name: 'FieldSelect',
38+
mixins: [ abstractField ],
39+
data () {
40+
return {
41+
isOpened: false
42+
}
43+
},
44+
computed: {
45+
selectedName () {
46+
return this.currentModelValue ? this.field.options.find(o => o.value === this.currentModelValue).name : undefined
47+
}
48+
},
49+
methods: {
50+
onClickInput () {
51+
if (this.isOpened) {
52+
this.isOpened = false
53+
return
54+
}
55+
this.isOpened = true
56+
},
57+
selectOption (option) {
58+
this.$emit('onInput', option.value)
59+
this.isOpened = false
60+
}
61+
}
62+
}
63+
</script>
64+
65+
<style>
66+
.vue-form-generator {
67+
.vfg-select {
68+
display: inline-flex;
69+
cursor: pointer;
70+
position: relative;
71+
user-select: none;
72+
border: 1px solid #cdcdcd;
73+
color: #202020;
74+
border-radius: 5px;
75+
width: 100%;
76+
min-height: 30px;
77+
background: #f4f4f4;
78+
}
79+
80+
.vfg-select-label {
81+
flex: 1 0 70%;
82+
align-content: center;
83+
padding: 0 .3rem;
84+
}
85+
86+
.vfg-select-label.text-muted {
87+
color: #5c5c5c;
88+
}
89+
90+
.vfg-select-list-container {
91+
position: absolute;
92+
padding: .3rem;
93+
top: 32px;
94+
left: 0;
95+
right: 0;
96+
background: #F4F4F4FF;
97+
border-radius: 3px;
98+
max-height: 250px;
99+
overflow-y: auto;
100+
}
101+
102+
.vfg-select-list {
103+
border-radius: inherit;
104+
}
105+
106+
.vfg-select-option {
107+
padding: .3rem .5rem;
108+
margin-bottom: .1rem;
109+
}
110+
111+
.vfg-select-option:first-child, .vfg-select-option:first-child:hover {
112+
border-radius: 3px;
113+
}
114+
115+
.vfg-select-option:last-child, .vfg-select-option:last-child:hover {
116+
border-radius: 3px;
117+
}
118+
119+
.vfg-select-option.selected {
120+
background: #d3d3d3;
121+
}
122+
123+
.vfg-select-option:hover {
124+
background: #d3d3d3;
125+
cursor: pointer;
126+
}
127+
}
128+
</style>

0 commit comments

Comments
 (0)