Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const SELECTORS = {
card: '.dx-cardview-card',
cardCheckbox: '.dx-checkbox-container',
selectAllButton: '[aria-label="Select all"]',
clearSelectionButton: '[aria-label="Clear selection"]',
};

const setup = (options: GridCoreOptions = {}): CardView => {
Expand All @@ -31,6 +32,8 @@ const getCardCheckboxes = (): NodeListOf<Element> => document.querySelectorAll(S

const getSelectAllButton = (): Element | null => document.querySelector(SELECTORS.selectAllButton);

const getClearSelectionButton = (): Element | null => document.querySelector(SELECTORS.clearSelectionButton);

const checkError = (): void => expect(throwError).toHaveBeenCalledWith('E1042', 'CardView');

jest.mock('@ts/grids/new/grid_core/options_validation/utils', () => ({
Expand Down Expand Up @@ -175,6 +178,30 @@ describe('when keyExpr is missing', () => {
});
});

describe('clear selection toolbar button', () => {
it('should clear selection after runtime selectedCardKeys option update', () => {
const cardView = setup({
Comment thread
markallenramirez marked this conversation as resolved.
keyExpr: 'id',
dataSource: [{ id: 1 }, { id: 2 }],
selection: {
mode: 'multiple',
},
selectedCardKeys: [],
});

expect(cardView.getSelectedCardKeys()).toEqual([]);

cardView.option('selectedCardKeys', [2]);

expect(cardView.getSelectedCardKeys()).toEqual([2]);

const clearSelectionButton = getClearSelectionButton();
clearSelectionButton?.dispatchEvent(new MouseEvent('click'));

expect(cardView.getSelectedCardKeys()).toEqual([]);
});
});
Comment thread
markallenramirez marked this conversation as resolved.

describe('selectAll with filters', () => {
it('should select only cards matching filterValue', () => {
const cardView = setup({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,29 @@ describe('SelectionController', () => {
selectionController.selectCards([1]);
expect(itemsController.items).toMatchSnapshot();
});

it('should only be called once when selectedCardKeys are updated', () => {
const {
selectionController,
optionsController,
} = setup({
keyExpr: 'id',
dataSource: [{ id: 1, value: 'test' }, { id: 2, value: 'test2' }],
selection: {
mode: 'multiple',
},
});

const selectCardsSpy = jest.spyOn(selectionController, 'selectCards');

optionsController.option('selectedCardKeys', [1]);

expect(selectCardsSpy).toHaveBeenCalledTimes(1);

optionsController.option('selectedCardKeys', []);

expect(selectCardsSpy).toHaveBeenCalledTimes(2);
});
Comment thread
markallenramirez marked this conversation as resolved.
});

describe('deselectCards', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,15 @@ export class SelectionController {
Need to get rid of `selectionHelper.peek()` inside of selectCards()
and pass selectionHelper from here
*/
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
this.selectionHelper.value;

const selectionHelper = this.selectionHelper.value;
const isLoaded = this.dataController.isLoaded.value;
if (isLoaded) {
const selectedCardKeys = this.selectedCardKeys.peek();
const keys = this.selectedCardKeys.value;
const hasExactSelectedItems = selectionHelper?.hasExactSelectedItems(keys);

this.selectCards(selectedCardKeys);
if (!hasExactSelectedItems) {
this.selectCards(keys);
Comment thread
markallenramirez marked this conversation as resolved.
}
Comment thread
markallenramirez marked this conversation as resolved.
}
});

Expand Down
11 changes: 11 additions & 0 deletions packages/devextreme/js/__internal/ui/selection/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,4 +402,15 @@ export default class Selection<
loadSelectedItemsWithFilter(): DeferredObj<unknown> {
return this._selectionStrategy.loadSelectedItemsWithFilter();
}

hasExactSelectedItems(keys: TKey[]): boolean {
const { selectedItems, keyOf } = this.options;
if (keys.length === selectedItems.length) {
return keys.every((key) => selectedItems.some((item) => {
const isKeysEqual = this._selectionStrategy.equalKeys(keyOf(item), key);
return isKeysEqual;
}));
}
return false;
}
}
Loading