-
Notifications
You must be signed in to change notification settings - Fork 6.8k
fix(list-key-manager): align matching logic with native listbox #7212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(list-key-manager): align matching logic with native listbox #7212
Conversation
src/cdk/a11y/list-key-manager.ts
Outdated
} else if (!hasWrapped && startIndex > 0 && i === total - 1) { | ||
i = -1; | ||
total = startIndex; | ||
hasWrapped = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use mod instead of manually wrapping?
const items = this._items.toArray();
// Start at 1 because we want to start searching at the item immediately
// following the current active item.
for (let i = 1; i < items.length; i++) {
const index = (this._activeItemIndex + i) % items.length;
if (items[index].getLabel!().toUpperCase().trim().indexOf(inputString) === 0) {
this.setActiveItem(index);
break;
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm interesting. It doesn't seem to work on smaller lists though, E.g. on one of the unit tests we have a list of one, two, three
but it never reaches three
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This always does what I'd expect:
var items = ['one', 'two', 'three'];
var activeIndex = 1;
for (let i = 1; i < items.length; i++) {
const index = (activeIndex + i) % items.length;
console.log(index, ' ', items[index]);
}
You mean for it to always skip the active item, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's supposed to skip it but then wrap around if it doesn't find anything else. I got it working like this:
for (let i = 1; i < items.length + 1; i++) {
const index = (this._activeItemIndex + i) % items.length;
if (items[index].getLabel!().toUpperCase().trim().indexOf(inputString) === 0) {
this.setActiveItem(index);
break;
}
}
Also I think you had a typo. The this.setActiveItem(i)
was supposed to be this.setActiveItem(index)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I did have that typo.
e122fba
to
c7068ba
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Please rebase |
Currently the typeahead option of the `ListKeyManager` looks for matches from start to end which can lead to some weird behavior where the user might be half-way down the list, but be sent up to the first item (e.g. in a list of `b, a, ba` it would always find `b`). These changes align the behavior closer to the native `listbox` by looking for the next match after the active item. If no match is found, the selection wraps around and starts looking from the beginning.
c7068ba
to
e7a0e5b
Compare
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Currently the typeahead option of the
ListKeyManager
looks for matches from start to end which can lead to some weird behavior where the user might be half-way down the list, but be sent up to the first item (e.g. in a list ofb, a, ba
it would always findb
). These changes align the behavior closer to the nativelistbox
by looking for the next match after the active item. If no match is found, the selection wraps around and starts looking from the beginning.