mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [autocomplete] add loopNavigation attributes (#22281)
* fix(components): [autocomplete] allow cyclic keyboard navigation * fix: update * docs: update Co-authored-by: btea <2356281422@qq.com> --------- Co-authored-by: btea <2356281422@qq.com>
This commit is contained in:
@@ -83,6 +83,7 @@ autocomplete/custom-header-footer
|
||||
| highlight-first-item | whether to highlight first item in remote search suggestions by default | ^[boolean] | false |
|
||||
| fit-input-width | whether the width of the dropdown is the same as the input | ^[boolean] | false |
|
||||
| popper-append-to-body ^(deprecated) | whether to append the dropdown to body. If the positioning of the dropdown is wrong, you can try to set this prop to false | ^[boolean] | false |
|
||||
| loop-navigation ^(2.11.4) | whether keyboard navigation loops from end to start | ^[boolean] | true |
|
||||
| [input props](./input.md#attributes) | — | — | — |
|
||||
|
||||
### Events
|
||||
|
||||
@@ -364,6 +364,63 @@ describe('Autocomplete.vue', () => {
|
||||
expect(document.body.querySelector('.highlighted')).toBeDefined()
|
||||
})
|
||||
|
||||
test('keyboard navigation should loop when loopNavigation is true', async () => {
|
||||
const wrapper = _mount({ debounce: 10, loopNavigation: true }, 'arr')
|
||||
await nextTick()
|
||||
|
||||
const target = wrapper.getComponent(Autocomplete).vm as InstanceType<
|
||||
typeof Autocomplete
|
||||
>
|
||||
const input = wrapper.find('input')
|
||||
|
||||
await input.trigger('focus')
|
||||
vi.runAllTimers()
|
||||
await nextTick()
|
||||
|
||||
const length = target.suggestions.length
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
await input.trigger('keydown.down')
|
||||
expect(target.highlightedIndex).toBe(i)
|
||||
}
|
||||
|
||||
await input.trigger('keydown.down')
|
||||
expect(target.highlightedIndex).toBe(0)
|
||||
|
||||
await input.trigger('keydown.up')
|
||||
expect(target.highlightedIndex).toBe(length - 1)
|
||||
})
|
||||
|
||||
test('keyboard navigation should not loop when loopNavigation is false', async () => {
|
||||
const wrapper = _mount({ debounce: 10, loopNavigation: false }, 'arr')
|
||||
await nextTick()
|
||||
|
||||
const target = wrapper.getComponent(Autocomplete).vm as InstanceType<
|
||||
typeof Autocomplete
|
||||
>
|
||||
const input = wrapper.find('input')
|
||||
|
||||
await input.trigger('focus')
|
||||
vi.runAllTimers()
|
||||
await nextTick()
|
||||
|
||||
const length = target.suggestions.length
|
||||
|
||||
await input.trigger('keydown.down')
|
||||
expect(target.highlightedIndex).toBe(0)
|
||||
|
||||
await input.trigger('keydown.up')
|
||||
expect(target.highlightedIndex).toBe(-1)
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
await input.trigger('keydown.down')
|
||||
expect(target.highlightedIndex).toBe(i)
|
||||
}
|
||||
|
||||
await input.trigger('keydown.down')
|
||||
expect(target.highlightedIndex).toBe(length - 1)
|
||||
})
|
||||
|
||||
test('fitInputWidth', async () => {
|
||||
const wrapper = _mount({
|
||||
fitInputWidth: true,
|
||||
|
||||
@@ -114,6 +114,13 @@ export const autocompleteProps = buildProps({
|
||||
* @description whether the width of the dropdown is the same as the input
|
||||
*/
|
||||
fitInputWidth: Boolean,
|
||||
/**
|
||||
* @description whether keyboard navigation loops from end to start
|
||||
*/
|
||||
loopNavigation: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
} as const)
|
||||
export type AutocompleteProps = ExtractPropTypes<typeof autocompleteProps>
|
||||
export type AutocompletePropsPublic = __ExtractPublicPropTypes<
|
||||
|
||||
@@ -348,12 +348,15 @@ const highlight = (index: number) => {
|
||||
if (!suggestionVisible.value || loading.value) return
|
||||
|
||||
if (index < 0) {
|
||||
highlightedIndex.value = -1
|
||||
return
|
||||
if (!props.loopNavigation) {
|
||||
highlightedIndex.value = -1
|
||||
return
|
||||
}
|
||||
index = suggestions.value.length - 1
|
||||
}
|
||||
|
||||
if (index >= suggestions.value.length) {
|
||||
index = suggestions.value.length - 1
|
||||
index = props.loopNavigation ? 0 : suggestions.value.length - 1
|
||||
}
|
||||
const suggestion = regionRef.value!.querySelector(
|
||||
`.${ns.be('suggestion', 'wrap')}`
|
||||
|
||||
Reference in New Issue
Block a user