Skip to content
Merged
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: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- 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:

```tsx
const { table } = useReactDataTable<T>({
data,
columns,
reactTableOptions: {
enableExpanding: true,
getSubRows: (_) => [],
getRowCanExpand: (row) => row.shouldRenderSubRow,
},
});
```

## [5.11.0] - 2025-06-03

### Added
Expand Down
3 changes: 3 additions & 0 deletions src/lib/ReactDataTable/ReactDataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const ReactDataTable = <TData, TFilter extends FilterModel = Record<string, neve
enableRowClick,
isStriped = true,
showClearSearchButton = true,
subRowComponent,
} = props;

const { pagination } = table.getState();
Expand Down Expand Up @@ -84,6 +85,7 @@ const ReactDataTable = <TData, TFilter extends FilterModel = Record<string, neve
enableExpanding={enableExpanding as boolean | ((row: Row<TData>) => boolean)}
rowStyle={rowStyle && rowStyle(row.original)}
fullRowSelectable={fullRowSelectable}
subRowComponent={subRowComponent as ReactDataTableProps<TData, TFilter>["subRowComponent"]}
/>
))}
</SortableContext>
Expand All @@ -100,6 +102,7 @@ const ReactDataTable = <TData, TFilter extends FilterModel = Record<string, neve
rowStyle={rowStyle && rowStyle(row.original)}
fullRowSelectable={fullRowSelectable}
hasPinnedColumns={table.getIsSomeColumnsPinned()}
subRowComponent={subRowComponent as ReactDataTableProps<TData, TFilter>["subRowComponent"]}
/>
))}
</>
Expand Down
5 changes: 5 additions & 0 deletions src/lib/ReactDataTable/ReactDataTableProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,9 @@ export interface ReactDataTableProps<TData, TFilter extends FilterModel> {
* @default true
*/
showClearSearchButton?: boolean;

/**
* A component to render as a sub-row for a specific row, this will be rendered additionally to the subrows.
*/
subRowComponent?: (row: Row<TData>) => React.ReactNode;
}
62 changes: 33 additions & 29 deletions src/lib/ReactDataTable/TableRows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { FilterModel } from "../types/TableState";
import { ReactDataTableProps } from "./ReactDataTableProps";

interface TableRowProps<TData, TFilter extends FilterModel = Record<string, never>>
extends Pick<ReactDataTableProps<TData, TFilter>, "onRowClick" | "enableRowClick"> {
extends Pick<ReactDataTableProps<TData, TFilter>, "onRowClick" | "enableRowClick" | "subRowComponent"> {
row: Row<TData>;
enableRowSelection?: boolean | ((row: Row<TData>) => boolean);
fullRowSelectable?: boolean;
Expand All @@ -27,39 +27,43 @@ const InternalTableRow = <TData, TFilter extends FilterModel = Record<string, ne
onRowClick,
enableRowClick,
hasPinnedColumns,
subRowComponent,
} = props;
const isRowSelectionEnabled =
(typeof enableRowSelection === "function" ? enableRowSelection(row) : enableRowSelection) && fullRowSelectable;
const isRowClickable = typeof enableRowClick === "function" ? enableRowClick(row) : enableRowClick;
return (
<tr
key={row.id}
ref={setNodeRef}
onClick={async () => {
if (isRowSelectionEnabled) {
row.toggleSelected();
} else if (isRowClickable && onRowClick) {
await onRowClick(row);
} else {
// Nothing to execute
}
}}
className={isRowSelectionEnabled || isRowClickable ? "cursor-pointer" : undefined}
style={rowStyle}
>
{row.getVisibleCells().map((cell) => (
<td
key={cell.id}
style={{
...cell.column.columnDef.meta?.cellStyle,
...(hasPinnedColumns ? getCommonPinningStyles(cell.column) : {}),
}}
className={cell.column.columnDef.meta?.cellClassName}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
<>
<tr
key={row.id}
ref={setNodeRef}
onClick={async () => {
if (isRowSelectionEnabled) {
row.toggleSelected();
} else if (isRowClickable && onRowClick) {
await onRowClick(row);
} else {
// Nothing to execute
}
}}
className={isRowSelectionEnabled || isRowClickable ? "cursor-pointer" : undefined}
style={rowStyle}
>
{row.getVisibleCells().map((cell) => (
<td
key={cell.id}
style={{
...cell.column.columnDef.meta?.cellStyle,
...(hasPinnedColumns ? getCommonPinningStyles(cell.column) : {}),
}}
className={cell.column.columnDef.meta?.cellClassName}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
{subRowComponent && row.getIsExpanded() && subRowComponent(row)}
</>
);
};

Expand Down
Loading