diff --git a/README.md b/README.md
index 785f21b..23d9224 100644
--- a/README.md
+++ b/README.md
@@ -406,11 +406,15 @@ shouldRenderSuggestions (size, loading) {
## [Events](#events)
+Below are the list of supported events. `@` is short-hand for
+[v-on](https://vuejs.org/v2/guide/events.html#Listening-to-Events).
+
| Prop | Returns | Description |
| :-------------------------------- | :-------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `@selected` | suggestionItem, index | suggestion select handler. equivalent to sectionConfigs `on-selected` but for all items |
| `@input`, `@focus`, `@blur`, etc. | \* | there is a transparent wrapper on the underlying `` so vue-autosuggest will use any DOM event you pass it for listening. This is implemented using `v-on:`. |
-| `@opened`, `@closed` | \* | suggestions visibility handler, indicates when the suggestions are opened and closed. |
+| `@opened`, `@closed` | \* | suggestions visibility handler, indicates when the suggestions are opened and closed. This is called alongside [shouldRenderSuggestions](#shouldRenderSuggestions). |
+| `@item-changed` | suggestionItem, index | when keying through the results, this event signals which item is highlighted before being selected. |
## Browser support
diff --git a/__tests__/autosuggest.test.js b/__tests__/autosuggest.test.js
index 091b0ea..66a87a9 100644
--- a/__tests__/autosuggest.test.js
+++ b/__tests__/autosuggest.test.js
@@ -784,25 +784,62 @@ describe("Autosuggest", () => {
expect(str).toMatchSnapshot();
});
});
- it("emits opened and closed events", async () => {
- const props = { ...defaultProps };
- props.inputProps = { ...defaultProps.inputProps };
- const wrapper = mount(Autosuggest, {
- propsData: props,
- });
+ it("emits opened and closed events", async () => {
+ const props = { ...defaultProps };
+ props.inputProps = { ...defaultProps.inputProps };
- const input = wrapper.find("input");
- input.setValue("G");
+ const wrapper = mount(Autosuggest, {
+ propsData: props,
+ });
+
+ const input = wrapper.find("input");
+ input.setValue("G");
+ input.trigger("keydown.down");
- // Wait for watchers
- await wrapper.vm.$nextTick(() => {
- expect(wrapper.emitted().opened).toBeTruthy();
- });
+ await wrapper.vm.$nextTick(() => {})
+ expect(wrapper.emitted().opened).toBeTruthy();
- input.trigger("keydown.esc");
- await wrapper.vm.$nextTick(() => {
+ input.trigger("keydown.esc");
+ await wrapper.vm.$nextTick(() => {})
expect(wrapper.emitted().closed).toBeTruthy();
});
- });
+
+ it("emits item-changed event", async () => {
+ const props = { ...defaultProps };
+ props.inputProps = { ...defaultProps.inputProps };
+
+ const wrapper = mount(Autosuggest, {
+ propsData: props,
+ });
+
+ const input = wrapper.find("input");
+ input.setValue("G");
+ input.trigger("keydown.down");
+ input.trigger("keydown.down");
+
+ await wrapper.vm.$nextTick(() => {})
+ expect(wrapper.emitted()['item-changed']).toHaveLength(2);
+ const itemChanged1 = wrapper.emitted()['item-changed'][0]
+ const itemChanged2 = wrapper.emitted()['item-changed'][1]
+
+ // Emits with item and index
+ expect(itemChanged1[0].item).toBe('clifford kits');
+ expect(itemChanged1[1]).toBe(0);
+ expect(itemChanged2[0].item).toBe('friendly chemistry');
+ expect(itemChanged2[1]).toBe(1);
+
+ input.trigger("keydown.up");
+ await wrapper.vm.$nextTick(() => {})
+ input.trigger("keydown.up");
+ await wrapper.vm.$nextTick(() => {})
+ await wrapper.vm.$nextTick(() => {})
+
+ // Ensure empty item-changed is emitted when user keys back
+ // to the input #177
+ expect(wrapper.emitted()['item-changed']).toHaveLength(4)
+ const itemChangedEmpty = wrapper.emitted()['item-changed'][3]
+ expect(itemChangedEmpty[0]).toBeNull();
+ expect(itemChangedEmpty[1]).toBeNull();
+ });
});
diff --git a/src/Autosuggest.vue b/src/Autosuggest.vue
index 380583b..ab549fa 100644
--- a/src/Autosuggest.vue
+++ b/src/Autosuggest.vue
@@ -310,7 +310,8 @@ export default {
if (newValue !== oldValue) {
this.$emit(newValue ? 'opened' : 'closed');
}
- }
+ },
+ immediate: true
}
},
created() {
@@ -399,7 +400,7 @@ export default {
this.setChangeItem(this.getItemByIndex(this.currentIndex));
this.didSelectFromOptions = true;
} else if (this.currentIndex == -1) {
- this.currentIndex = null;
+ this.setChangeItem(null)
this.internalValue = this.searchInputOriginal;
e.preventDefault();
}
@@ -433,9 +434,10 @@ export default {
setChangeItem(item, overrideOriginalInput = false) {
if (this.currentIndex === null || !item) {
this.currentItem = null;
+ this.$emit('item-changed', null, null)
} else if (item) {
this.currentItem = item;
- this.$emit('itemChanged', item, this.currentIndex)
+ this.$emit('item-changed', item, this.currentIndex)
const v = this.getSuggestionValue(item)
this.internalValue = v;
if (overrideOriginalInput) {