Skip to content

Commit

Permalink
Merge pull request #445 from EdwardEB/v2
Browse files Browse the repository at this point in the history
Add MRT_TableBodyEmptyRow component to render when table has no rows
  • Loading branch information
alessandrojcm authored Dec 1, 2024
2 parents 24fc9da + 23b0a59 commit 58083ae
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 40 deletions.
37 changes: 4 additions & 33 deletions packages/mantine-react-table/src/components/body/MRT_TableBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
type TableProps,
TableTbody,
type TableTbodyProps,
Text,
} from '@mantine/core';
import { MRT_TableBodyRow, Memo_MRT_TableBodyRow } from './MRT_TableBodyRow';
import { useMRT_RowVirtualizer } from '../../hooks/useMRT_RowVirtualizer';
Expand All @@ -18,6 +17,7 @@ import {
type MRT_VirtualItem,
} from '../../types';
import { parseFromValuesOrFunc } from '../../utils/utils';
import { MRT_TableBodyEmptyRow } from './MRT_TableBodyEmptyRow';

export interface MRT_TableBodyProps<TData extends MRT_RowData>
extends TableTbodyProps {
Expand All @@ -42,16 +42,14 @@ export const MRT_TableBody = <TData extends MRT_RowData>({
enableStickyFooter,
enableStickyHeader,
layoutMode,
localization,
mantineTableBodyProps,
memoMode,
renderDetailPanel,
renderEmptyRowsFallback,
rowPinningDisplayMode,
},
refs: { tableFooterRef, tableHeadRef, tablePaperRef },
refs: { tableFooterRef, tableHeadRef },
} = table;
const { columnFilters, globalFilter, isFullScreen, rowPinning } = getState();
const { isFullScreen, rowPinning } = getState();

const tableBodyProps = {
...parseFromValuesOrFunc(mantineTableBodyProps, { table }),
Expand Down Expand Up @@ -133,34 +131,7 @@ export const MRT_TableBody = <TData extends MRT_RowData>({
>
{tableBodyProps?.children ??
(!rows.length ? (
<tr
className={clsx(
'mrt-table-body-row',
layoutMode?.startsWith('grid') && classes['empty-row-tr-grid'],
)}
>
<td
className={clsx(
'mrt-table-body-cell',
layoutMode?.startsWith('grid') &&
classes['empty-row-td-grid'],
)}
colSpan={table.getVisibleLeafColumns().length}
>
{renderEmptyRowsFallback?.({ table }) ?? (
<Text
__vars={{
'--mrt-paper-width': `${tablePaperRef.current?.clientWidth}`,
}}
className={clsx(classes['empty-row-td-content'])}
>
{globalFilter || columnFilters.length
? localization.noResultsFound
: localization.noRecordsToDisplay}
</Text>
)}
</td>
</tr>
<MRT_TableBodyEmptyRow {...commonRowProps} />
) : (
<>
{(virtualRows ?? rows).map(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import clsx from 'clsx';
import classes from './MRT_TableBody.module.css';
import { useMemo } from 'react';
import { type TableProps, Text, TableTd, TableTrProps } from '@mantine/core';
import { MRT_TableBodyRow } from './MRT_TableBodyRow';
import {
type MRT_Row,
type MRT_RowData,
type MRT_TableInstance,
} from '../../types';
import { createRow } from '@tanstack/react-table';
import { MRT_ExpandButton } from '../buttons/MRT_ExpandButton';

interface Props<TData extends MRT_RowData> extends TableTrProps {
table: MRT_TableInstance<TData>;
tableProps: Partial<TableProps>;
}

export const MRT_TableBodyEmptyRow = <TData extends MRT_RowData>({
table,
tableProps,
...commonRowProps
}: Props<TData>) => {
const {
getState,
options: {
layoutMode,
localization,
renderDetailPanel,
renderEmptyRowsFallback,
},
refs: { tablePaperRef },
} = table;
const { columnFilters, globalFilter } = getState();

const emptyRow = useMemo(
() =>
createRow(
table as any,
'mrt-row-empty',
{} as TData,
0,
0,
) as MRT_Row<TData>,
[],
);

const emptyRowProps = {
...commonRowProps,
renderedRowIndex: 0,
row: emptyRow,
virtualRow: undefined,
};

return (
<MRT_TableBodyRow
table={table}
tableProps={tableProps}
className={clsx(
'mrt-table-body-row',
layoutMode?.startsWith('grid') && classes['empty-row-tr-grid'],
)}
{...emptyRowProps}
>
{renderDetailPanel && (
<TableTd
className={clsx(
'mrt-table-body-cell',
layoutMode?.startsWith('grid') && classes['empty-row-td-grid'],
)}
colSpan={1}
>
<MRT_ExpandButton row={emptyRow} table={table} />
</TableTd>
)}
<td
className={clsx(
'mrt-table-body-cell',
layoutMode?.startsWith('grid') && classes['empty-row-td-grid'],
)}
colSpan={table.getVisibleLeafColumns().length}
>
{renderEmptyRowsFallback?.({ table }) ?? (
<Text
__vars={{
'--mrt-paper-width': `${tablePaperRef.current?.clientWidth}`,
}}
className={clsx(classes['empty-row-td-content'])}
>
{globalFilter || columnFilters.length
? localization.noResultsFound
: localization.noRecordsToDisplay}
</Text>
)}
</td>
</MRT_TableBodyRow>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface Props<TData extends MRT_RowData> extends TableTrProps {
}

export const MRT_TableBodyRow = <TData extends MRT_RowData>({
children,
columnVirtualizer,
numRows,
pinnedRowIds,
Expand Down Expand Up @@ -189,7 +190,7 @@ export const MRT_TableBodyRow = <TData extends MRT_RowData>({
{virtualPaddingLeft ? (
<Box component="td" display="flex" w={virtualPaddingLeft} />
) : null}
{(virtualColumns ?? row.getVisibleCells()).map(
{children ? children : (virtualColumns ?? row.getVisibleCells()).map(
(cellOrVirtualCell, renderedColumnIndex) => {
let cell = cellOrVirtualCell as MRT_Cell<TData>;
if (columnVirtualizer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
type MRT_VirtualItem,
} from '../../types';
import { parseFromValuesOrFunc } from '../../utils/utils';
import { MRT_EditCellTextInput } from '../inputs/MRT_EditCellTextInput';

interface Props<TData extends MRT_RowData> extends TableTdProps {
parentRowRef: RefObject<HTMLTableRowElement>;
Expand Down Expand Up @@ -57,8 +58,15 @@ export const MRT_TableDetailPanel = <TData extends MRT_RowData>({
...rest,
};

const internalEditComponents = row
.getAllCells()
.filter((cell) => cell.column.columnDef.columnDefType === 'data')
.map((cell) => (
<MRT_EditCellTextInput cell={cell} key={cell.id} table={table} />
));

const DetailPanel =
!isLoading && row.getIsExpanded() && renderDetailPanel?.({ row, table });
!isLoading && row.getIsExpanded() && renderDetailPanel?.({ row, table, internalEditComponents });

return (
<TableTr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
type MRT_TableInstance,
} from '../../types';
import { parseFromValuesOrFunc } from '../../utils/utils';
import { MRT_EditCellTextInput } from '../inputs/MRT_EditCellTextInput';

interface Props<TData extends MRT_RowData> extends ActionIconProps {
row: MRT_Row<TData>;
Expand Down Expand Up @@ -42,10 +43,18 @@ export const MRT_ExpandButton = <TData extends MRT_RowData>({
}),
...rest,
};

const internalEditComponents = row
.getAllCells()
.filter((cell) => cell.column.columnDef.columnDefType === 'data')
.map((cell) => (
<MRT_EditCellTextInput cell={cell} key={cell.id} table={table} />
));

const canExpand = row.getCanExpand();
const isExpanded = row.getIsExpanded();

const DetailPanel = !!renderDetailPanel?.({ row, table });
const DetailPanel = !!renderDetailPanel?.({ row, table, internalEditComponents });

const handleToggleExpand = (event: MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
Expand All @@ -59,9 +68,8 @@ export const MRT_ExpandButton = <TData extends MRT_RowData>({
<Tooltip
disabled={!canExpand && !DetailPanel}
label={
actionIconProps?.title ?? (isExpanded
? localization.collapse
: localization.expand)
actionIconProps?.title ??
(isExpanded ? localization.collapse : localization.expand)
}
openDelay={1000}
withinPortal
Expand Down
1 change: 1 addition & 0 deletions packages/mantine-react-table/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export * from './components/MantineReactTable';
export * from './components/body/MRT_TableBody';
export * from './components/body/MRT_TableBodyCell';
export * from './components/body/MRT_TableBodyCellValue';
export * from './components/body/MRT_TableBodyEmptyRow';
export * from './components/body/MRT_TableBodyRow';
export * from './components/body/MRT_TableBodyRowGrabHandle';
export * from './components/body/MRT_TableBodyRowPinButton';
Expand Down
1 change: 1 addition & 0 deletions packages/mantine-react-table/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,7 @@ export type MRT_TableOptions<TData extends MRT_RowData> = Omit<
renderDetailPanel?: (props: {
row: MRT_Row<TData>;
table: MRT_TableInstance<TData>;
internalEditComponents: ReactNode[];
}) => ReactNode;
renderEditRowModalContent?: (props: {
internalEditComponents: ReactNode[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useState } from 'react';
import { Flex, Stack, Switch, Title } from '@mantine/core';
import { Center, Flex, Group, Stack, Switch, Title, Text } from '@mantine/core';
import {
type MRT_Cell,
type MRT_ColumnOrderState,
MRT_EditActionButtons,
type MRT_TableOptions,
MantineReactTable,
MRT_ColumnDef,
useMantineReactTable,
} from '../../src';
import { faker } from '@faker-js/faker';
import { type Meta } from '@storybook/react';
Expand Down Expand Up @@ -1238,3 +1239,64 @@ export const EditingTurnedOnDynamically = () => {
</Stack>
);
};

export const EditingInDetailPannel = () => {
const [withData, setWithData] = useState(false);

const columns = [
{
accessorKey: 'firstName',
header: 'First Name',
},
{
accessorKey: 'lastName',
header: 'Last Name',
},
{
accessorKey: 'address',
header: 'Address',
},
{
accessorKey: 'state',
header: 'State',
},
{
accessorKey: 'phoneNumber',
enableEditing: false,
header: 'Phone Number',
},
];

const table = useMantineReactTable({
columns,
data: withData ? data : [],
renderDetailPanel: ({ table, row, internalEditComponents }) => (
<Center>
<form onSubmit={(e) => e.preventDefault()}>
<Group gap="md" pb={24} pt={16}>
{internalEditComponents}
</Group>
</form>
<Flex justify="flex-end">
<MRT_EditActionButtons row={row} table={table} variant="text" />
</Flex>
</Center>
),
renderEmptyRowsFallback: () => (
<Center>
<Text>This table is empty, click on the chevron to add a record</Text>
</Center>
),
});

return (
<Stack>
<Switch
checked={withData}
label="Show data"
onChange={(e) => setWithData(e.currentTarget.checked)}
/>
<MantineReactTable table={table} />
</Stack>
);
};
Loading

0 comments on commit 58083ae

Please sign in to comment.