Skip to content

Commit acdce1b

Browse files
authored
add option subRowComponent to render subrow (#80)
1 parent 6cb28ef commit acdce1b

4 files changed

Lines changed: 57 additions & 29 deletions

File tree

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- option `subRowComponent` to pass a render-function for a subrow. This will be rendered additionally to the subrows and if not wanted, make sure the subrows are passed as empty arrayd [], following an example:
13+
14+
```tsx
15+
const { table } = useReactDataTable<T>({
16+
data,
17+
columns,
18+
reactTableOptions: {
19+
enableExpanding: true,
20+
getSubRows: (_) => [],
21+
getRowCanExpand: (row) => row.shouldRenderSubRow,
22+
},
23+
});
24+
```
25+
1026
## [5.11.0] - 2025-06-03
1127

1228
### Added

src/lib/ReactDataTable/ReactDataTable.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const ReactDataTable = <TData, TFilter extends FilterModel = Record<string, neve
4747
enableRowClick,
4848
isStriped = true,
4949
showClearSearchButton = true,
50+
subRowComponent,
5051
} = props;
5152

5253
const { pagination } = table.getState();
@@ -84,6 +85,7 @@ const ReactDataTable = <TData, TFilter extends FilterModel = Record<string, neve
8485
enableExpanding={enableExpanding as boolean | ((row: Row<TData>) => boolean)}
8586
rowStyle={rowStyle && rowStyle(row.original)}
8687
fullRowSelectable={fullRowSelectable}
88+
subRowComponent={subRowComponent as ReactDataTableProps<TData, TFilter>["subRowComponent"]}
8789
/>
8890
))}
8991
</SortableContext>
@@ -100,6 +102,7 @@ const ReactDataTable = <TData, TFilter extends FilterModel = Record<string, neve
100102
rowStyle={rowStyle && rowStyle(row.original)}
101103
fullRowSelectable={fullRowSelectable}
102104
hasPinnedColumns={table.getIsSomeColumnsPinned()}
105+
subRowComponent={subRowComponent as ReactDataTableProps<TData, TFilter>["subRowComponent"]}
103106
/>
104107
))}
105108
</>

src/lib/ReactDataTable/ReactDataTableProps.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,9 @@ export interface ReactDataTableProps<TData, TFilter extends FilterModel> {
113113
* @default true
114114
*/
115115
showClearSearchButton?: boolean;
116+
117+
/**
118+
* A component to render as a sub-row for a specific row, this will be rendered additionally to the subrows.
119+
*/
120+
subRowComponent?: (row: Row<TData>) => React.ReactNode;
116121
}

src/lib/ReactDataTable/TableRows.tsx

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { FilterModel } from "../types/TableState";
77
import { ReactDataTableProps } from "./ReactDataTableProps";
88

99
interface TableRowProps<TData, TFilter extends FilterModel = Record<string, never>>
10-
extends Pick<ReactDataTableProps<TData, TFilter>, "onRowClick" | "enableRowClick"> {
10+
extends Pick<ReactDataTableProps<TData, TFilter>, "onRowClick" | "enableRowClick" | "subRowComponent"> {
1111
row: Row<TData>;
1212
enableRowSelection?: boolean | ((row: Row<TData>) => boolean);
1313
fullRowSelectable?: boolean;
@@ -27,39 +27,43 @@ const InternalTableRow = <TData, TFilter extends FilterModel = Record<string, ne
2727
onRowClick,
2828
enableRowClick,
2929
hasPinnedColumns,
30+
subRowComponent,
3031
} = props;
3132
const isRowSelectionEnabled =
3233
(typeof enableRowSelection === "function" ? enableRowSelection(row) : enableRowSelection) && fullRowSelectable;
3334
const isRowClickable = typeof enableRowClick === "function" ? enableRowClick(row) : enableRowClick;
3435
return (
35-
<tr
36-
key={row.id}
37-
ref={setNodeRef}
38-
onClick={async () => {
39-
if (isRowSelectionEnabled) {
40-
row.toggleSelected();
41-
} else if (isRowClickable && onRowClick) {
42-
await onRowClick(row);
43-
} else {
44-
// Nothing to execute
45-
}
46-
}}
47-
className={isRowSelectionEnabled || isRowClickable ? "cursor-pointer" : undefined}
48-
style={rowStyle}
49-
>
50-
{row.getVisibleCells().map((cell) => (
51-
<td
52-
key={cell.id}
53-
style={{
54-
...cell.column.columnDef.meta?.cellStyle,
55-
...(hasPinnedColumns ? getCommonPinningStyles(cell.column) : {}),
56-
}}
57-
className={cell.column.columnDef.meta?.cellClassName}
58-
>
59-
{flexRender(cell.column.columnDef.cell, cell.getContext())}
60-
</td>
61-
))}
62-
</tr>
36+
<>
37+
<tr
38+
key={row.id}
39+
ref={setNodeRef}
40+
onClick={async () => {
41+
if (isRowSelectionEnabled) {
42+
row.toggleSelected();
43+
} else if (isRowClickable && onRowClick) {
44+
await onRowClick(row);
45+
} else {
46+
// Nothing to execute
47+
}
48+
}}
49+
className={isRowSelectionEnabled || isRowClickable ? "cursor-pointer" : undefined}
50+
style={rowStyle}
51+
>
52+
{row.getVisibleCells().map((cell) => (
53+
<td
54+
key={cell.id}
55+
style={{
56+
...cell.column.columnDef.meta?.cellStyle,
57+
...(hasPinnedColumns ? getCommonPinningStyles(cell.column) : {}),
58+
}}
59+
className={cell.column.columnDef.meta?.cellClassName}
60+
>
61+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
62+
</td>
63+
))}
64+
</tr>
65+
{subRowComponent && row.getIsExpanded() && subRowComponent(row)}
66+
</>
6367
);
6468
};
6569

0 commit comments

Comments
 (0)