|
1 | 1 | <template>
|
2 | 2 | <div class="mv-select" v-clickoutside="handleClose">
|
3 |
| - <div class="input-field col s12"> |
4 |
| - <div class="select-wrapper"> |
5 |
| - <span class="caret">▼</span> |
6 |
| - <input type="text" |
7 |
| - class="select-dropdown" |
8 |
| - readonly="true" |
9 |
| - :value="selectedLabel" |
10 |
| - @focus="handleFocus" |
11 |
| - @click="handleClick" |
12 |
| - ref="mvSelect" |
13 |
| - > |
14 |
| - <transition |
15 |
| - name="mv-top" |
16 |
| - @before-enter="handleMenuEnter"> |
17 |
| - <ul id="select-options" |
18 |
| - class="dropdown-content select-dropdown" |
19 |
| - :class="{'mv-select__multiple': multiple}" |
20 |
| - v-show="avisible" |
21 |
| - ref="options"> |
22 |
| - <el-option |
23 |
| - :value="placeholder" |
24 |
| - created |
25 |
| - v-if="placeholder" |
26 |
| - disabled> |
27 |
| - </el-option> |
28 |
| - <slot></slot> |
29 |
| - </ul> |
30 |
| - </transition> |
31 |
| - </div> |
32 |
| - <label>Materialize Select</label> |
| 3 | + <div class="select-wrapper"> |
| 4 | + <span class="caret">▼</span> |
| 5 | + <input type="text" |
| 6 | + class="select-dropdown" |
| 7 | + readonly="true" |
| 8 | + :value="selectedLabel" |
| 9 | + @focus="handleFocus" |
| 10 | + @click="handleClick"> |
| 11 | + <transition |
| 12 | + name="mv-top" |
| 13 | + @before-enter="handleMenuEnter"> |
| 14 | + <ul id="select-options" |
| 15 | + class="dropdown-content select-dropdown" |
| 16 | + :class="{'mv-select__multiple': multiple}" |
| 17 | + v-show="visible" |
| 18 | + ref="options"> |
| 19 | + <mv-option |
| 20 | + v-if="placeholder" |
| 21 | + :value="placeholder" |
| 22 | + disabled> |
| 23 | + </mv-option> |
| 24 | + <slot></slot> |
| 25 | + </ul> |
| 26 | + </transition> |
33 | 27 | </div>
|
| 28 | + <label v-if="label">{{label}}</label> |
34 | 29 | </div>
|
35 | 30 | </template>
|
36 | 31 |
|
37 | 32 | <script>
|
38 |
| - import ElOption from './option.vue' |
39 |
| - import Clickoutside from 'mvui/src/utils/clickoutside' |
| 33 | + import MvOption from './option.vue' |
| 34 | + import Clickoutside from 'main/utils/clickoutside' |
| 35 | + import {getValueByPath} from 'main/utils/util' |
40 | 36 |
|
41 | 37 | export default {
|
42 | 38 | name: 'MvSelect',
|
43 | 39 |
|
44 | 40 | componentName: 'MvSelect',
|
45 | 41 |
|
46 |
| - directives: { Clickoutside }, |
| 42 | + directives: {Clickoutside}, |
| 43 | +
|
| 44 | + components: { |
| 45 | + MvOption |
| 46 | + }, |
47 | 47 |
|
48 | 48 | props: {
|
49 | 49 | value: {
|
|
54 | 54 | default: 'value'
|
55 | 55 | },
|
56 | 56 | placeholder: {
|
57 |
| - type: [String, Object, Number], |
| 57 | + type: [String, Number, Object], |
58 | 58 | default: ''
|
59 | 59 | },
|
60 | 60 | multiple: {
|
61 | 61 | type: Boolean
|
62 |
| - } |
| 62 | + }, |
| 63 | + label: String |
63 | 64 | },
|
| 65 | +
|
64 | 66 | data () {
|
65 | 67 | return {
|
66 | 68 | options: [],
|
67 | 69 | cachedOptions: [],
|
68 |
| - avisible: false, |
| 70 | + visible: false, |
69 | 71 | isSelect: true,
|
70 |
| - selectedLabel: '', |
71 |
| - createdLabel: '', |
72 |
| - filterable: '', |
73 |
| - createdSelected: '', |
74 |
| - checkbox: false |
| 72 | + selectedLabel: '' |
75 | 73 | }
|
76 | 74 | },
|
77 |
| - components: { |
78 |
| - ElOption |
79 |
| - }, |
80 |
| - created () { |
81 |
| - this.$on('handleOptionClick', this.handleOptionSelect) |
| 75 | +
|
| 76 | + watch: { |
| 77 | + value (val) { |
| 78 | + this.setSelected() |
| 79 | + this.$emit('change', val) |
| 80 | + } |
82 | 81 | },
|
| 82 | +
|
83 | 83 | methods: {
|
84 | 84 | handleOptionSelect (option) {
|
85 | 85 | if (this.multiple) {
|
|
93 | 93 | this.$emit('input', value)
|
94 | 94 | } else {
|
95 | 95 | this.$emit('input', option.value)
|
96 |
| - this.avisible = false |
| 96 | + this.visible = false |
97 | 97 | }
|
98 | 98 | },
|
99 | 99 | getValueIndex (arr = [], value) {
|
100 | 100 | const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]'
|
101 | 101 | if (!isObject) {
|
102 | 102 | return arr.indexOf(value)
|
| 103 | + } else { |
| 104 | + const valueKey = this.valueKey |
| 105 | + let index = -1 |
| 106 | + arr.some((item, i) => { |
| 107 | + if (getValueByPath(item, valueKey) === getValueByPath(value, valueKey)) { |
| 108 | + index = i |
| 109 | + return true |
| 110 | + } |
| 111 | + return false |
| 112 | + }) |
| 113 | + return index |
103 | 114 | }
|
104 | 115 | },
|
105 | 116 | handleFocus () {
|
106 |
| - this.avisible = true |
107 |
| - }, |
108 |
| - handleBlur () { |
109 |
| - setTimeout(() => { |
110 |
| - this.avisible = false |
111 |
| - }, 200) |
| 117 | + this.visible = true |
112 | 118 | },
|
113 | 119 | handleClose () {
|
114 |
| - this.avisible = false |
| 120 | + this.visible = false |
115 | 121 | },
|
116 | 122 | setSelected () {
|
117 | 123 | if (!this.multiple) {
|
118 | 124 | let option = this.getOption(this.value)
|
119 |
| - if (option.created) { |
120 |
| - this.createdLabel = option.currentLabel |
121 |
| - this.createdSelected = true |
122 |
| - } else { |
123 |
| - this.createdSelected = false |
124 |
| - } |
125 | 125 | this.selectedLabel = option.currentLabel
|
126 | 126 | if (!option.currentLabel && this.placeholder) {
|
127 | 127 | this.selectedLabel = this.placeholder
|
128 | 128 | }
|
129 |
| - this.selected = option |
130 |
| - if (this.filterable) this.query = this.selectedLabel |
131 | 129 | return
|
132 | 130 | }
|
133 | 131 | let result = []
|
134 | 132 | if (Array.isArray(this.value)) {
|
135 | 133 | this.value.forEach(value => {
|
136 |
| - result.push(this.getOption(value).label) |
| 134 | + result.push(this.getOption(value).currentLabel) |
137 | 135 | })
|
138 | 136 | }
|
139 | 137 | this.selectedLabel = result
|
140 | 138 | },
|
141 | 139 | getOption (value) {
|
142 | 140 | let option
|
143 | 141 | const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]'
|
144 |
| - for (let i = this.cachedOptions.length - 1; i >= 0; i--) { |
| 142 | + for (let i = 0; i <= this.cachedOptions.length - 1; i++) { |
145 | 143 | const cachedOption = this.cachedOptions[i]
|
146 | 144 | const isEqual = isObject
|
147 |
| - ? this.getValueByPath(cachedOption.value, this.valueKey) === this.getValueByPath(value, this.valueKey) |
| 145 | + ? getValueByPath(cachedOption.value, this.valueKey) === getValueByPath(value, this.valueKey) |
148 | 146 | : cachedOption.value === value
|
149 | 147 | if (isEqual) {
|
150 | 148 | option = cachedOption
|
|
164 | 162 | return newOption
|
165 | 163 | },
|
166 | 164 | handleClick () {
|
167 |
| - this.avisible !== this.avisible |
| 165 | + this.visible !== this.visible |
168 | 166 | },
|
169 | 167 | handleMenuEnter (el) {
|
170 | 168 | el.style.top = 0
|
171 |
| - }, |
172 |
| - getValueByPath (object, prop) { |
173 |
| - prop = prop || '' |
174 |
| - const paths = prop.split('.') |
175 |
| - let current = object |
176 |
| - let result = null |
177 |
| - for (let i = 0, j = paths.length; i < j; i++) { |
178 |
| - const path = paths[i] |
179 |
| - if (!current) break |
180 |
| -
|
181 |
| - if (i === j - 1) { |
182 |
| - result = current[path] |
183 |
| - break |
184 |
| - } |
185 |
| - current = current[path] |
186 |
| - } |
187 |
| - return result |
188 | 169 | }
|
189 | 170 | },
|
190 |
| - computed: {}, |
191 | 171 | mounted () {
|
192 | 172 | this.setSelected()
|
193 | 173 | },
|
194 |
| - watch: { |
195 |
| - 'value' (val) { |
196 |
| - this.setSelected() |
197 |
| - this.$emit('change', val) |
198 |
| - } |
| 174 | +
|
| 175 | + created () { |
| 176 | + this.$on('handleOptionClick', this.handleOptionSelect) |
199 | 177 | }
|
200 | 178 | }
|
201 | 179 | </script>
|
0 commit comments