Commit 06a74f9ed76645f476b4818aaaad136798a76012
1 parent
f7f65c84
Allow select to navigate AutoComplete custom children
Showing
1 changed file
with
42 additions
and
9 deletions
Show diff stats
src/components/select/select.vue
| ... | ... | @@ -92,6 +92,20 @@ |
| 92 | 92 | } |
| 93 | 93 | }; |
| 94 | 94 | |
| 95 | + const findOptionsInVNode = (node) => { | |
| 96 | + const opts = node.componentOptions; | |
| 97 | + if (opts && opts.tag === 'Option') return [node]; | |
| 98 | + if (!node.children) return []; | |
| 99 | + const options = node.children.reduce( | |
| 100 | + (arr, el) => [...arr, ...findOptionsInVNode(el)], [] | |
| 101 | + ).filter(Boolean); | |
| 102 | + return options.length > 0 ? options : []; | |
| 103 | + }; | |
| 104 | + | |
| 105 | + const extractOptions = (options) => options.reduce((options, slotEntry) => { | |
| 106 | + return options.concat(findOptionsInVNode(slotEntry)); | |
| 107 | + }, []); | |
| 108 | + | |
| 95 | 109 | export default { |
| 96 | 110 | name: 'iSelect', |
| 97 | 111 | mixins: [ Emitter, Locale ], |
| ... | ... | @@ -275,16 +289,39 @@ |
| 275 | 289 | }, |
| 276 | 290 | selectOptions() { |
| 277 | 291 | const selectOptions = []; |
| 292 | + const slotOptions = (this.slotOptions || []); | |
| 278 | 293 | let optionCounter = -1; |
| 279 | 294 | const currentIndex = this.focusIndex; |
| 280 | 295 | const selectedValues = this.values.map(({value}) => value); |
| 281 | - if (this.autoComplete) return this.slotOptions; | |
| 296 | + if (this.autoComplete) { | |
| 297 | + const copyChildren = (node, fn) => { | |
| 298 | + return { | |
| 299 | + ...node, | |
| 300 | + children: (node.children || []).map(fn).map(child => copyChildren(child, fn)) | |
| 301 | + }; | |
| 302 | + }; | |
| 303 | + const autoCompleteOptions = extractOptions(slotOptions); | |
| 304 | + const selectedSlotOption = autoCompleteOptions[currentIndex]; | |
| 305 | + | |
| 306 | + return slotOptions.map(node => copyChildren(node, (child) => { | |
| 307 | + if (child !== selectedSlotOption) return child; | |
| 308 | + return { | |
| 309 | + ...child, | |
| 310 | + componentOptions: { | |
| 311 | + ...child.componentOptions, | |
| 312 | + propsData: { | |
| 313 | + ...child.componentOptions.propsData, | |
| 314 | + isFocused: true, | |
| 315 | + } | |
| 316 | + } | |
| 317 | + }; | |
| 318 | + })); | |
| 319 | + } | |
| 282 | 320 | |
| 283 | - for (let option of (this.slotOptions || [])) { | |
| 321 | + for (let option of slotOptions) { | |
| 284 | 322 | |
| 285 | 323 | const cOptions = option.componentOptions; |
| 286 | 324 | if (!cOptions) continue; |
| 287 | - | |
| 288 | 325 | if (cOptions.tag.match(optionGroupRegexp)){ |
| 289 | 326 | let children = cOptions.children; |
| 290 | 327 | |
| ... | ... | @@ -315,11 +352,7 @@ |
| 315 | 352 | return selectOptions; |
| 316 | 353 | }, |
| 317 | 354 | flatOptions(){ |
| 318 | - return this.selectOptions.reduce((options, option) => { | |
| 319 | - const isOptionGroup = option.componentOptions.tag.match(optionGroupRegexp); | |
| 320 | - if (isOptionGroup) return options.concat(option.componentOptions.children || []); | |
| 321 | - else return options.concat(option); | |
| 322 | - }, []); | |
| 355 | + return extractOptions(this.selectOptions); | |
| 323 | 356 | }, |
| 324 | 357 | selectTabindex(){ |
| 325 | 358 | return this.disabled || this.filterable ? -1 : 0; |
| ... | ... | @@ -595,7 +628,7 @@ |
| 595 | 628 | } |
| 596 | 629 | }, |
| 597 | 630 | focusIndex(index){ |
| 598 | - if (index < 0) return; | |
| 631 | + if (index < 0 || this.autoComplete) return; | |
| 599 | 632 | // update scroll |
| 600 | 633 | const optionValue = this.flatOptions[index].componentOptions.propsData.value; |
| 601 | 634 | const optionInstance = findChild(this, ({$options}) => { | ... | ... |