Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e97d4b1

Browse files
committed
fix(cdk/a11y): clear active item in key manager if it is removed from the list
The active item in the `ListKeyManager` gets updated on keyboard events, but if the list changes between them, we may end up in a state where it's pointing to an item that's not in the DOM anymore. This can cause something like `aria-activedescendant` to point to an invalid element. These changes add some logic that clear the active element if it's removed from the list and there's nothing at its new index.
1 parent 2d79ab7 commit e97d4b1

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

‎src/cdk/a11y/key-manager/list-key-manager.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,42 @@ describe('Key managers', () => {
9393
expect(keyManager.activeItem!.getLabel()).toBe('one');
9494
});
9595

96+
it('should update the active item if the current one is removed and there is ' +
97+
'a new one at the same index', () => {
98+
expect(keyManager.activeItemIndex).toBe(0);
99+
expect(keyManager.activeItem!.getLabel()).toBe('one');
100+
101+
itemList.items = [new FakeFocusable('new-0'), new FakeFocusable('new-1')];
102+
itemList.notifyOnChanges();
103+
104+
expect(keyManager.activeItemIndex).toBe(0);
105+
expect(keyManager.activeItem!.getLabel()).toBe('new-0');
106+
});
107+
108+
it('should clear the active item if nothing exists at the new index', () => {
109+
keyManager.setActiveItem(2);
110+
111+
expect(keyManager.activeItemIndex).toBe(2);
112+
expect(keyManager.activeItem!.getLabel()).toBe('three');
113+
114+
itemList.items = itemList.items.slice(0, 1);
115+
itemList.notifyOnChanges();
116+
117+
expect(keyManager.activeItemIndex).toBe(-1);
118+
expect(keyManager.activeItem).toBe(null);
119+
});
120+
121+
it('should clear the active item if the list is cleared', () => {
122+
expect(keyManager.activeItemIndex).toBe(0);
123+
expect(keyManager.activeItem!.getLabel()).toBe('one');
124+
125+
itemList.items = [];
126+
itemList.notifyOnChanges();
127+
128+
expect(keyManager.activeItemIndex).toBe(-1);
129+
expect(keyManager.activeItem).toBe(null);
130+
});
131+
96132
it('should start off the activeItem as null', () => {
97133
expect(new ListKeyManager([]).activeItem).toBeNull();
98134
});

‎src/cdk/a11y/key-manager/list-key-manager.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
7070
const itemArray = newItems.toArray();
7171
const newIndex = itemArray.indexOf(this._activeItem);
7272

73-
if (newIndex > -1 && newIndex !== this._activeItemIndex) {
73+
if (newIndex === -1) {
74+
this.updateActiveItem(this._activeItemIndex);
75+
} else if (newIndex !== this._activeItemIndex) {
7476
this._activeItemIndex = newIndex;
7577
}
7678
}
@@ -349,7 +351,7 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
349351

350352
// Explicitly check for `null` and `undefined` because other falsy values are valid.
351353
this._activeItem = activeItem == null ? null : activeItem;
352-
this._activeItemIndex = index;
354+
this._activeItemIndex = activeItem==null ? -1 : index;
353355
}
354356

355357
/**

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /