Skip to content
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

Passing generateGroupId props #3520

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/TreeDataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface TreeDataGridProps<R, SR = unknown, K extends Key = Key>
) => Record<string, readonly NoInfer<R>[]>;
expandedGroupIds: ReadonlySet<unknown>;
onExpandedGroupIdsChange: (expandedGroupIds: Set<unknown>) => void;
generateGroupId?: (groupKey: string, parentId?: string) => string;
}

type GroupByDictionary<TRow> = Record<
Expand All @@ -62,6 +63,7 @@ function TreeDataGrid<R, SR, K extends Key>(
rowGrouper,
expandedGroupIds,
onExpandedGroupIdsChange,
generateGroupId,
...props
}: TreeDataGridProps<R, SR, K>,
ref: React.Ref<DataGridHandle>
Expand Down Expand Up @@ -144,6 +146,15 @@ function TreeDataGrid<R, SR, K extends Key>(
if (!groupedRows) return [rawRows, isGroupRow];

const flattenedRows: Array<R | GroupRow<R>> = [];

const groupIdGenerator = (groupKey: string, parentId?: string) => {
if (generateGroupId !== undefined && typeof generateGroupId === 'function') {
return generateGroupId(groupKey, parentId);
}

return `${parentId}__${groupKey}`;
};

const expandGroup = (
rows: GroupByDictionary<R> | readonly R[],
parentId: string | undefined,
Expand All @@ -154,8 +165,7 @@ function TreeDataGrid<R, SR, K extends Key>(
return;
}
Object.keys(rows).forEach((groupKey, posInSet, keys) => {
// TODO: should users have control over the generated key?
const id = parentId !== undefined ? `${parentId}__${groupKey}` : groupKey;
const id = groupIdGenerator(groupKey, parentId);
const isExpanded = expandedGroupIds.has(id);
const { childRows, childGroups, startRowIndex } = rows[groupKey];

Expand Down Expand Up @@ -185,7 +195,7 @@ function TreeDataGrid<R, SR, K extends Key>(
function isGroupRow(row: R | GroupRow<R>): row is GroupRow<R> {
return allGroupRows.has(row);
}
}, [expandedGroupIds, groupedRows, rawRows]);
}, [expandedGroupIds, groupedRows, rawRows, generateGroupId]);

const rowHeight = useMemo(() => {
if (typeof rawRowHeight === 'function') {
Expand Down
38 changes: 35 additions & 3 deletions test/TreeDataGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,12 @@ function rowKeyGetter(row: Row) {
return row.id;
}

function TestGrid({ groupBy }: { groupBy: string[] }) {
interface TestGridProps {
groupBy: string[];
generateGroupId: ((groupKey: string, parentId?: string) => string) | undefined;
}

function TestGrid({ groupBy, generateGroupId }: TestGridProps) {
const [rows, setRows] = useState(initialRows);
const [selectedRows, setSelectedRows] = useState((): ReadonlySet<number> => new Set());
const [expandedGroupIds, setExpandedGroupIds] = useState(
Expand Down Expand Up @@ -122,12 +127,16 @@ function TestGrid({ groupBy }: { groupBy: string[] }) {
onExpandedGroupIdsChange={setExpandedGroupIds}
onRowsChange={setRows}
onPaste={onPaste}
{...(generateGroupId && { generateGroupId })}
/>
);
}

function setup(groupBy: string[]) {
render(<TestGrid groupBy={groupBy} />);
function setup(
groupBy: string[],
generateGroupId?: (groupKey: string, parentId?: string) => string
) {
render(<TestGrid groupBy={groupBy} generateGroupId={generateGroupId} />);
}

function getHeaderCellsContent() {
Expand Down Expand Up @@ -161,6 +170,15 @@ test('should group by multiple columns', () => {
expect(getRows()).toHaveLength(4);
});

test('should group by multiple columns when passing generateGroupId', () => {
setup(['country', 'year'], (groupKey, parentId) =>
parentId !== undefined ? `${groupKey}#${parentId}` : groupKey
);
expect(getTreeGrid()).toHaveAttribute('aria-rowcount', '13');
expect(getHeaderCellsContent()).toStrictEqual(['', 'Country', 'Year', 'Sport', 'Id']);
expect(getRows()).toHaveLength(4);
});

test('should ignore duplicate groupBy columns', () => {
setup(['year', 'year', 'year']);
expect(getTreeGrid()).toHaveAttribute('aria-rowcount', '10');
Expand All @@ -184,6 +202,20 @@ test('should toggle group when group cell is clicked', async () => {
expect(getRows()).toHaveLength(5);
});

test('should toggle group when group cell is clicked and is passing `generateGroupId` props', async () => {
setup(['country', 'year'], (groupKey, parentId) =>
parentId !== undefined ? `${groupKey}#${parentId}` : groupKey
);
expect(getTreeGrid()).toHaveAttribute('aria-rowcount', '13');
expect(getHeaderCellsContent()).toStrictEqual(['', 'Country', 'Year', 'Sport', 'Id']);
await userEvent.click(screen.getByRole('gridcell', { name: 'USA' }));
expect(getRows()).toHaveLength(6);
await userEvent.click(screen.getByRole('gridcell', { name: 'Canada' }));
expect(getRows()).toHaveLength(8);
await userEvent.click(screen.getByRole('gridcell', { name: '2020' }));
expect(getRows()).toHaveLength(9);
});

test('should toggle group using keyboard', async () => {
setup(['year']);
expect(getRows()).toHaveLength(5);
Expand Down