Skip to content

Commit

Permalink
fix(material/list): add command+A for MacOs "select all" functionality.
Browse files Browse the repository at this point in the history
Fixes a bug in Angular Material `list` when using MacOs `command`+`a` does not work for 'select all functionality'.

Fixes #24781
  • Loading branch information
volvachev authored and Egor Volvachev committed Apr 16, 2022
1 parent 4193037 commit 503e0eb
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
82 changes: 82 additions & 0 deletions src/material/list/selection-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,88 @@ describe('MatSelectionList without forms', () => {
);
});

it('should select all items using command(metaKey) + a', () => {
listOptions.forEach(option => (option.componentInstance.disabled = false));
const event = createKeyboardEvent('keydown', A, undefined, {meta: true});

expect(listOptions.some(option => option.componentInstance.selected)).toBe(false);

dispatchEvent(selectionList.nativeElement, event);
fixture.detectChanges();

expect(listOptions.every(option => option.componentInstance.selected)).toBe(true);
});

it('should not select disabled items when pressing command(metaKey) + a', () => {
const event = createKeyboardEvent('keydown', A, undefined, {meta: true});

listOptions.slice(0, 2).forEach(option => (option.componentInstance.disabled = true));
fixture.detectChanges();

expect(listOptions.map(option => option.componentInstance.selected)).toEqual([
false,
false,
false,
false,
false,
]);

dispatchEvent(selectionList.nativeElement, event);
fixture.detectChanges();

expect(listOptions.map(option => option.componentInstance.selected)).toEqual([
false,
false,
true,
true,
true,
]);
});

it('should select all items using command(metaKey) + a if some items are selected', () => {
const event = createKeyboardEvent('keydown', A, undefined, {meta: true});

listOptions.slice(0, 2).forEach(option => (option.componentInstance.selected = true));
fixture.detectChanges();

expect(listOptions.some(option => option.componentInstance.selected)).toBe(true);

dispatchEvent(selectionList.nativeElement, event);
fixture.detectChanges();

expect(listOptions.every(option => option.componentInstance.selected)).toBe(true);
});

it('should deselect all with command(metaKey) + a if all options are selected', () => {
const event = createKeyboardEvent('keydown', A, undefined, {meta: true});

listOptions.forEach(option => (option.componentInstance.selected = true));
fixture.detectChanges();

expect(listOptions.every(option => option.componentInstance.selected)).toBe(true);

dispatchEvent(selectionList.nativeElement, event);
fixture.detectChanges();

expect(listOptions.every(option => option.componentInstance.selected)).toBe(false);
});

it('should dispatch the selectionChange event when selecting via command(metaKey) + a', () => {
const spy = spyOn(fixture.componentInstance, 'onSelectionChange');
listOptions.forEach(option => (option.componentInstance.disabled = false));
const event = createKeyboardEvent('keydown', A, undefined, {meta: true});

dispatchEvent(selectionList.nativeElement, event);
fixture.detectChanges();

expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith(
jasmine.objectContaining({
options: listOptions.map(option => option.componentInstance),
}),
);
});

it('should be able to jump focus down to an item by typing', fakeAsync(() => {
const listEl = selectionList.nativeElement;
const manager = selectionList.componentInstance._keyManager;
Expand Down
2 changes: 1 addition & 1 deletion src/material/list/selection-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ export class MatSelectionList
if (
keyCode === A &&
this.multiple &&
hasModifierKey(event, 'ctrlKey') &&
hasModifierKey(event, 'ctrlKey', 'metaKey') &&
!manager.isTyping()
) {
const shouldSelect = this.options.some(option => !option.disabled && !option.selected);
Expand Down

0 comments on commit 503e0eb

Please sign in to comment.