Skip to content

Commit c2b92c9

Browse files
author
Jeff
committed
WIP: wrap search input in scoped slot, move attributes to computed prop
1 parent 8c622b6 commit c2b92c9

File tree

1 file changed

+104
-30
lines changed

1 file changed

+104
-30
lines changed

src/components/Select.vue

Lines changed: 104 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -323,29 +323,9 @@
323323
</span>
324324
</slot>
325325

326-
<input
327-
ref="search"
328-
v-model="search"
329-
@keydown.delete="maybeDeleteValue"
330-
@keyup.esc="onEscape"
331-
@keydown.up.prevent="typeAheadUp"
332-
@keydown.down.prevent="typeAheadDown"
333-
@keydown.enter.prevent="typeAheadSelect"
334-
@keydown.tab="onTab"
335-
@blur="onSearchBlur"
336-
@focus="onSearchFocus"
337-
type="search"
338-
class="form-control"
339-
autocomplete="off"
340-
:disabled="disabled"
341-
:placeholder="searchPlaceholder"
342-
:tabindex="tabindex"
343-
:readonly="!searchable"
344-
:id="inputId"
345-
role="combobox"
346-
:aria-expanded="dropdownOpen"
347-
aria-label="Search for option"
348-
>
326+
<slot name="search" v-bind="scope.search">
327+
<input v-bind="scope.search.attributes" v-on="scope.search.events">
328+
</slot>
349329

350330
</div>
351331
<div class="vs__actions">
@@ -583,7 +563,7 @@
583563
},
584564
585565
/**
586-
* Enable/disable creating options from searchInput.
566+
* Enable/disable creating options from searchEl.
587567
* @type {Boolean}
588568
*/
589569
taggable: {
@@ -721,6 +701,16 @@
721701
selectOnTab: {
722702
type: Boolean,
723703
default: false
704+
},
705+
706+
/**
707+
* Query Selector used to find the search input
708+
* when the 'search' scoped slot is used.
709+
* @type {String}
710+
*/
711+
searchInputQuerySelector: {
712+
type: String,
713+
default: '[type=search]'
724714
}
725715
},
726716
@@ -871,7 +861,7 @@
871861
onAfterSelect(option) {
872862
if (this.closeOnSelect) {
873863
this.open = !this.open
874-
this.$refs.search.blur()
864+
this.searchEl.blur()
875865
}
876866
877867
if (this.clearSearchOnSelect) {
@@ -885,14 +875,14 @@
885875
* @return {void}
886876
*/
887877
toggleDropdown(e) {
888-
if (e.target === this.$refs.openIndicator || e.target === this.$refs.search || e.target === this.$refs.toggle ||
878+
if (e.target === this.$refs.openIndicator || e.target === this.searchEl || e.target === this.$refs.toggle ||
889879
e.target.classList.contains('selected-tag') || e.target === this.$el) {
890880
if (this.open) {
891-
this.$refs.search.blur() // dropdown will close on blur
881+
this.searchEl.blur() // dropdown will close on blur
892882
} else {
893883
if (!this.disabled) {
894884
this.open = true
895-
this.$refs.search.focus()
885+
this.searchEl.focus()
896886
}
897887
}
898888
}
@@ -957,7 +947,7 @@
957947
*/
958948
onEscape() {
959949
if (!this.search.length) {
960-
this.$refs.search.blur()
950+
this.searchEl.blur()
961951
} else {
962952
this.search = ''
963953
}
@@ -996,7 +986,7 @@
996986
* @return {this.value}
997987
*/
998988
maybeDeleteValue() {
999-
if (!this.$refs.search.value.length && this.mutableValue) {
989+
if (!this.searchEl.value.length && this.mutableValue) {
1000990
return this.multiple ? this.mutableValue.pop() : this.mutableValue = null
1001991
}
1002992
},
@@ -1044,11 +1034,95 @@
10441034
*/
10451035
onMousedown() {
10461036
this.mousedown = true
1037+
},
1038+
1039+
/**
1040+
* Search 'input' KeyBoardEvent handler.
1041+
* @param e {KeyboardEvent}
1042+
* @return {Function}
1043+
*/
1044+
onSearchKeyDown (e) {
1045+
switch (e.which) {
1046+
case 8:
1047+
// delete
1048+
return this.maybeDeleteValue();
1049+
}
1050+
},
1051+
1052+
/**
1053+
* Search 'input' KeyBoardEvent handler.
1054+
* @param e {KeyboardEvent}
1055+
* @return {Function}
1056+
*/
1057+
onSearchKeyUp (e) {
1058+
switch (e.which) {
1059+
case 27:
1060+
// esc
1061+
return this.onEscape();
1062+
case 38:
1063+
// up.prevent
1064+
e.preventDefault();
1065+
return this.typeAheadUp();
1066+
case 40:
1067+
// down.prevent
1068+
e.preventDefault();
1069+
return this.typeAheadDown();
1070+
case 13:
1071+
// enter.prevent
1072+
e.preventDefault();
1073+
return this.typeAheadSelect();
1074+
case 9:
1075+
// tab
1076+
return this.onTab();
1077+
}
10471078
}
10481079
},
10491080
10501081
computed: {
10511082
1083+
/**
1084+
* Find the search input DOM element.
1085+
* @returns {HTMLInputElement}
1086+
*/
1087+
searchEl () {
1088+
return !!this.$scopedSlots['search']
1089+
? this.$refs.selectedOptions.querySelector(this.searchInputQuerySelector)
1090+
: this.$refs.search;
1091+
},
1092+
1093+
/**
1094+
* The object to be bound to the $slots.search scoped slot.
1095+
* @returns {Object}
1096+
*/
1097+
scope () {
1098+
return {
1099+
search: {
1100+
attributes: {
1101+
'disabled': this.disabled,
1102+
'placeholder': this.searchPlaceholder,
1103+
'tabindex': this.tabindex,
1104+
'readonly': !this.searchable,
1105+
'id': this.inputId,
1106+
'value': this.search,
1107+
'aria-expanded': this.dropdownOpen,
1108+
'aria-label': 'Search for option',
1109+
'ref': 'search',
1110+
'role': 'combobox',
1111+
'type': 'search',
1112+
'autocomplete': 'off',
1113+
'class': 'form-control',
1114+
},
1115+
events: {
1116+
'keydown': this.onSearchKeyDown,
1117+
'keyup': this.onSearchKeyUp,
1118+
'blur': this.onSearchBlur,
1119+
'focus': this.onSearchFocus,
1120+
'input': (e) => this.search = e.target.value,
1121+
},
1122+
},
1123+
};
1124+
},
1125+
10521126
/**
10531127
* Classes to be output on .dropdown
10541128
* @return {Object}

0 commit comments

Comments
 (0)