Skip to content

Commit d88a33f

Browse files
authored
fix(select): checking for a search value before emitting search event causes the last letter deleted to not emit an event (#414)
1 parent b4b8f90 commit d88a33f

5 files changed

Lines changed: 60 additions & 3 deletions

File tree

β€Žplayground/PlaygroundLayout.vueβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const links = [
2020
{ value: "/menu-header", label: "Menu Header" },
2121
{ value: "/menu-positioning", label: "Menu Positioning" },
2222
{ value: "/keyboard-navigation", label: "Keyboard Navigation" },
23+
{ value: "/search-event", label: "Search Event" },
2324
];
2425
2526
const router = useRouter();
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<script setup lang="ts">
2+
import type { Option } from "../../src";
3+
import { ref } from "vue";
4+
import VueSelect from "../../src";
5+
6+
const selected = ref<string | null>(null);
7+
const search = ref<string | null>(null);
8+
9+
const options = ref<Option<string>[]>([
10+
{ label: "Alice's Adventures in Wonderland", value: "alice" },
11+
{ label: "A Wizard of Earthsea", value: "wizard" },
12+
{ label: "Harry Potter and the Philosopher's Stone", value: "harry_potter_1" },
13+
{ label: "Harry Potter and the Chamber of Secrets", value: "harry_potter_2" },
14+
]);
15+
16+
const handleCreateOption = (value: string) => {
17+
options.value.push({ label: value, value });
18+
selected.value = value;
19+
};
20+
</script>
21+
22+
<template>
23+
<p class="selected-value">
24+
Search text: {{ search }}
25+
</p>
26+
27+
<VueSelect
28+
v-model="selected"
29+
:options="options"
30+
:is-multi="false"
31+
:is-taggable="true"
32+
placeholder="Pick a book"
33+
@option-created="(value) => handleCreateOption(value)"
34+
@search="(value) => search = value"
35+
>
36+
<template #taggable-no-options="{ option }">
37+
<div class="custom-taggable-no-options">
38+
Create option: {{ option }}
39+
</div>
40+
</template>
41+
</VueSelect>
42+
43+
<p class="selected-value">
44+
Selected book value: {{ selected || "none" }}
45+
</p>
46+
</template>

β€Žplayground/main.tsβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import MenuPositioning from "./demos/MenuPositioning.vue";
1313
import MultiSelect from "./demos/MultiSelect.vue";
1414
import MultiSelectTaggable from "./demos/MultiSelectTaggable.vue";
1515
import NoSelectOnBlur from "./demos/NoSelectOnBlur.vue";
16+
import SearchEvent from "./demos/SearchEvent.vue";
1617
import SelectIsLoading from "./demos/SelectIsLoading.vue";
1718
import SingleSelect from "./demos/SingleSelect.vue";
1819
import TaggableNoOptionsSlot from "./demos/TaggableNoOptionsSlot.vue";
@@ -38,6 +39,7 @@ const router = createRouter({
3839
{ path: "/menu-header", component: MenuHeader },
3940
{ path: "/menu-positioning", component: MenuPositioning },
4041
{ path: "/keyboard-navigation", component: KeyboardNavigation },
42+
{ path: "/search-event", component: SearchEvent },
4143
],
4244
});
4345

β€Žsrc/Select.spec.tsβ€Ž

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,15 @@ describe("search emit", () => {
379379
expect(wrapper.emitted("search")).toStrictEqual([["United"]]);
380380
});
381381

382+
it("should emit the search event when clearing the input", async () => {
383+
const wrapper = mount(VueSelect, { props: { modelValue: null, options } });
384+
385+
await inputSearch(wrapper, "United");
386+
await inputSearch(wrapper, "");
387+
388+
expect(wrapper.emitted("search")).toStrictEqual([["United"], [""]]);
389+
});
390+
382391
it("should emit an empty string for the search when the menu is closed", async () => {
383392
const wrapper = mount(VueSelect, { props: { modelValue: null, options } });
384393

β€Žsrc/Select.vueβ€Ž

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ function closeMenu() {
154154
menuOpen.value = false;
155155
search.value = "";
156156
focusedOption.value = -1;
157-
emit("search", "");
158157
emit("menuClosed");
159158
};
160159
@@ -337,8 +336,8 @@ defineExpose({
337336
// Watch the search input value to emit search events and auto-open the menu when typing
338337
watch(
339338
() => search.value,
340-
() => {
341-
if (props.isSearchable && search.value) {
339+
(newSearch, oldSearch) => {
340+
if (props.isSearchable && newSearch !== oldSearch) {
342341
emit("search", search.value);
343342
focusedOption.value = -1;
344343

0 commit comments

Comments
Β (0)