Skip to content

Commit

Permalink
fix: check/uncheck event emitted when multi check/uncheck via shift c…
Browse files Browse the repository at this point in the history
…lick (#1965)

* fix: check/uncheck event emitted when multi check/uncheck via shift click

* fix: exclude rowKeys whose checkbox state has not changed from check event

* fix:check event has wrong rowKeys

* chore: separate the logic of getting a rowKey into a function

* test: add tests

* fix: wrong range of rowkeys
  • Loading branch information
jajugoguma authored Sep 18, 2023
1 parent 99c79d9 commit 2f6569c
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 5 deletions.
49 changes: 49 additions & 0 deletions packages/toast-ui.grid/cypress/integration/eventBus.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,55 @@ describe('rowHeader: checkbox', () => {

cy.wrap(uncheckCallback).should('be.calledOnce');
});

it(`checkBetween / uncheckBetween by ${type}`, () => {
cy.createGrid({
data: [...data, ...data],
columns,
draggable: true,
bodyHeight: 150,
width: 500,
rowHeaders: ['rowNum', 'checkbox'],
});

const checkCallback = cy.stub();
const uncheckCallback = cy.stub();

cy.getByCls('cell-row-header').get('input').eq(1).as('firstCheckbox');
cy.getByCls('cell-row-header').get('input').eq(2).as('secondCheckbox');
cy.getByCls('cell-row-header').get('input').eq(-1).as('lastCheckbox');

cy.gridInstance().invoke('on', 'check', checkCallback);
cy.gridInstance().invoke('on', 'uncheck', uncheckCallback);

if (type === 'UI') {
// In Cypress 4.9.0, there is no way to test Shift-click
// cy.get('@secondCheckbox').click();
// cy.get('@firstCheckbox').click();
// cy.get('@lastCheckbox').click({
// shiftKey: true, // not available in Cypress 4.9.0
// });
} else {
cy.gridInstance().invoke('check', 1);
cy.gridInstance().invoke('checkBetween', 0, 3);

cy.wrap(checkCallback).should('be.calledWithMatch', { rowKeys: [0, 2, 3] });
}

if (type === 'UI') {
// In Cypress 4.9.0, there is no way to test Shift-click
// cy.get('@secondCheckbox').click();
// cy.get('@firstCheckbox').click();
// cy.get('@lastCheckbox').click({
// shiftKey: true, // not available in Cypress 4.9.0
// });
} else {
cy.gridInstance().invoke('uncheck', 1);
cy.gridInstance().invoke('uncheckBetween', 0, 3);

cy.wrap(uncheckCallback).should('be.calledWithMatch', { rowKeys: [0, 2, 3] });
}
});
});
});

Expand Down
19 changes: 14 additions & 5 deletions packages/toast-ui.grid/src/dispatch/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
isScrollPagination,
isFiltered,
getCreatedRowInfos,
getCheckStateChangedRowkeysInRange,
} from '../query/data';
import {
updateSummaryValueByCell,
Expand Down Expand Up @@ -378,7 +379,8 @@ export function check(store: Store, rowKey: RowKey) {
/**
* Occurs when a checkbox in row header is checked
* @event Grid#check
* @property {number | string} rowKey - rowKey of the checked row
* @property {number | string} [rowKey] - rowKey of the checked row(when single check via click)
* @property {Array<number | string>} [rowKeys] - rowKeys of the checked rows(when multiple check via shift-click)
* @property {Grid} instance - Current grid instance
*/
eventBus.trigger('check', gridEvent);
Expand All @@ -403,7 +405,8 @@ export function uncheck(store: Store, rowKey: RowKey) {
/**
* Occurs when a checkbox in row header is unchecked
* @event Grid#uncheck
* @property {number | string} rowKey - rowKey of the unchecked row
* @property {number | string} [rowKey] - rowKey of the unchecked row(when single check via click)
* @property {Array<number | string>} [rowKeys] - rowKeys of the unchecked rows(when multiple unchecked via shift-click)
* @property {Grid} instance - Current grid instance
*/
eventBus.trigger('uncheck', gridEvent);
Expand All @@ -415,11 +418,10 @@ export function setCheckboxBetween(
startRowKey: RowKey,
endRowKey?: RowKey
) {
const { data } = store;
const { data, id } = store;
const { clickedCheckboxRowkey } = data;
const targetRowKey = endRowKey || clickedCheckboxRowkey;

data.clickedCheckboxRowkey = startRowKey;
const eventBus = getEventBus(id);

if (isNil(targetRowKey)) {
if (value) {
Expand All @@ -431,9 +433,16 @@ export function setCheckboxBetween(
}

const range = getIndexRangeOfCheckbox(store, startRowKey, targetRowKey);
const checkStateChangedRowkeys = getCheckStateChangedRowkeysInRange(store, value, range);

data.clickedCheckboxRowkey = startRowKey;

setRowsAttributeInRange(store, 'checked', value, range);
setCheckedAllRows(store);

const gridEvent = new GridEvent({ rowKeys: checkStateChangedRowkeys });

eventBus.trigger(value ? 'check' : 'uncheck', gridEvent);
}

export function checkAll(store: Store, allPage?: boolean) {
Expand Down
18 changes: 18 additions & 0 deletions packages/toast-ui.grid/src/query/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,21 @@ export function changeRawDataToOriginDataForTree(rawData: Row[]) {
.filter((row) => isNil(row._attributes?.tree?.parentRowKey))
.map((row) => changeRowToOriginRowForTree(row));
}

export function getCheckStateChangedRowkeysInRange(
store: Store,
checkState: boolean,
range: [number, number]
) {
const { data } = store;
const { filteredRawData } = data;

const rowKeys: RowKey[] = [];
for (let i = range[0]; i < range[1]; i += 1) {
if (filteredRawData[i]._attributes.checked !== checkState) {
rowKeys.push(getRowKeyByIndexWithPageRange(data, i));
}
}

return rowKeys;
}
1 change: 1 addition & 0 deletions packages/toast-ui.grid/types/event/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface GridEventProps {
nextValue?: CellValue;
event?: MouseEvent;
rowKey?: RowKey | null;
rowKeys?: RowKey[] | null;
columnName?: string | null;
prevRowKey?: RowKey | null;
prevColumnName?: string | null;
Expand Down

0 comments on commit 2f6569c

Please sign in to comment.