MaterialReactTable定制以及使用

import React, { useEffect, useMemo, useState } from 'react';
import {
  MaterialReactTable,
  useMaterialReactTable,
  type MRT_ColumnDef,
  MRT_EditActionButtons,
  MRT_Row,
} from 'material-react-table';
import { Box, Button, DialogActions, DialogContent, DialogTitle, IconButton, InputAdornment, MenuItem, Pagination, Select, TextField, Tooltip, Typography } from '@mui/material';
import { Search, Clear, Edit, Delete } from '@mui/icons-material';
type ArgInstance = {
  data?: any[];
  api?: any;
  columns: MRT_ColumnDef<any>[];
  loading?: boolean;
  enablePager?: boolean;
  searchParam?: any;
};
type Setting = {
  enablePager?: boolean;
  searchParam?: any;
};
type State = {
  loading?: boolean;
};
type TableInstance = {
  data: ArgInstance,
  settings?: Setting;
  state?: State;
  leftForm?: any;
  rightForm?: any;
  topForm?: any;
};
const loadingErrorMessage = 'Loading Error';

const MaterialStaticTable = (props: TableInstance) => {
  //should be memoized or stable
  const { data, columns, } = props.data;
  const showRowsPage: any = [10, 20, 30, 50];
  const [enableColumnOrdering, setEnableColumnOrdering] = useState(true);
  const [enableRowVirtual, setEnableRowVirtual] = useState(true);
  const [isError, setIsError] = useState(false);
  const [isLoading, setIsLoading] = useState(props.state?.loading || false);
  const [isFetching, setIsFetching] = useState(false);
  const [globalFilter, setGlobalFilter] = useState('');
  const [frontPager, setFrontPager] = useState(true);

  const [tableData, setTableData] = useState<any[]>(data || []);
  const [pagination, setPagination] = useState({
    pageIndex: frontPager ? 0 : 1, // 对于支持后端分页的接口0页代表查所有
    pageSize: 10,
  });
  const [columnsData, setColumnsData] = useState<any>(columns || []);
  const [isEnablePager, setIsEnablePager] = useState(props.data.enablePager || true);
  const [rowCount, setRowCount] = useState(tableData?.length || 0);
  const [totalPage, setTotalPage] = useState(Math.ceil((tableData?.length ?? 0) / pagination.pageSize || 10));
  const [searchCondition, setSearchCondition] = useState('');

  const [tablesReqInfo, setTablesReqInfo] = useState<any>(null);
  const [tablesData, setTablesData] = useState(data || []);
  const [filterString, setFilterString] = useState<any>('');
  const [loadTime, setLoadTime] = useState<any>(0);

  //DELETE action
  const openDeleteConfirmModal = (row: MRT_Row<any>) => {
    if (window.confirm('Are you sure you want to delete this user?')) {
      // deleteUser(row.original.id);
      console.log('delete user', row.original, row.original.id);
      setTableData(tableData.filter((item) => item.id !== row.original?.id))
    }
  };
  const refreshTable = () => {
    // Refresh table logic here
  };
  useEffect(() => {
    // console.log('tableData', tableData);
    setRowCount(tableData?.length || 0);
    setTotalPage(Math.ceil((tableData?.length ?? 0) / pagination.pageSize || 10));
  }, [tableData]);
  const table = useMaterialReactTable({
    columns: columns,
    data: tableData,

    enablePagination: isEnablePager,
    enableRowVirtualization: !enableRowVirtual,

    muiCircularProgressProps: {
      color: 'warning',
      thickness: 5,
      size: 80,
    },
    muiSkeletonProps: {
      animation: 'pulse',
      height: 28,
    },
    // enableColumnVirtualization: enableColumnVirtualization,
    initialState: {
      // pagination,
      // density: 'compact', // 表格紧密 compact comfortable
      // showGlobalFilter: !isPrint,
      // ...customState,
    },
    // 当包含2时禁止选择
    muiSelectCheckboxProps: ({ row }) => ({
      disabled: row.original.state.indexOf("2") > 0,
    }),

    manualPagination: !frontPager, // 是否前端分页(接口请求走后端分页)
    rowCount: rowCount, // 数据总数
    pageCount: pagination.pageSize,
    state: {
      pagination,
      // pagination: pagination,
      isLoading: isLoading,
      showAlertBanner: isError,
      showProgressBars: isFetching,
    },
    muiSearchTextFieldProps: {
      placeholder: 'Search Column Options',
      sx: { minWidth: '18rem' },
      variant: 'outlined',
    },
    muiTablePaperProps: {
      sx: { mb: '1.5rem' },
      id: 'relevant-column-options-table'//'column-options-table',
    },
    // rowNumberDisplayMode: "static",
    // renderDetailPanel: ({ row }) => (
    //   <Typography
    //     color={row.original.description ? 'secondary.main' : 'text.secondary'}
    //   >
    //     {row.original.description || 'No Description Provided... Yet...'}
    //   </Typography>
    // ),
    // muiPaginationProps: {
    //   color: 'primary',
    //   showRowsPerPage: false,
    //   rowsPerPageOptions: showRowsPage, //showRowsPage,
    //   shape: 'rounded',
    //   variant: 'outlined',
    //   size: 'small',
    //   defaultPage: frontPager ? 0 : 1,
    //   count: totalPage,
    //   page: (frontPager ? 1 : 0) + pagination.pageIndex,
    // onChange: (event, page) => {
    //   // fix default page init to 0 cause two request
    //   // console.log('onchange', (frontPager ? -1 : 0) + page, page);
    //   setPagination({ ...pagination, ...{ pageIndex: (frontPager ? -1 : 0) + page } });
    // },
    // }, 
    // defaultColumn: {
    //   minSize: 1,
    //   maxSize: 100,
    //   // size: document.body.clientWidth / columns.length - 3,
    // },

    paginationDisplayMode: 'pages',
    // enableStickyHeader: true,
    enableStickyFooter: true,
    enableColumnOrdering: enableColumnOrdering,
    enableColumnResizing: true, //false为自动分布行
    layoutMode: 'grid',
    enableFullScreenToggle: false, // 全屏

    enableColumnDragging: true, // 列拖拽
    enableDensityToggle: false, // 密度
    enableColumnActions: false, // 列操作
    enableFilters: true, // 控制全局过滤以及每一列过滤(开启会导致表格右上角出现过滤框)
    manualFiltering: true,
    // enableColumnVirtualization: true,//虚拟滚动

    enableGlobalFilter: false, // /searchFromEnd,
    positionGlobalFilter: 'right', // "left",
    ///
    onGlobalFilterChange: setGlobalFilter,
    onColumnFiltersChange: (filterData: any) => { },
    onShowColumnFiltersChange: (filterData: any) => { },
    enableColumnFilterModes: true,// 开启列过滤模式
    ///
    // columnFilterDisplayMode: "custom",
    enableRowNumbers: true,
    // enableRowDragging: true,
    enableTableHead: true,
    enableMultiSort: true,
    manualSorting: false, // 手动排序
    enableEditing: true,
    editDisplayMode: 'modal', //default
    onEditingRowSave: ({ table, values }) => {
      //validate data
      //save data to api
      console.log('onEditingRowSave', table, values);
      table.setEditingRow(null); //exit editing mode
    },
    // muiEditTextFieldProps: ({ cell, row, table }) => ({
    //   onBlur: (event) => {
    //     //validate data
    //     //save data to api and/or rerender table
    //     // table.setEditingCell(null) is called automatically onBlur internally
    //   },
    // }),
    onEditingRowCancel: () => {
      //clear any validation errors
    },
    // custom edit components
    // 自定义编辑组件
    renderEditRowDialogContent: ({ table, row, internalEditComponents }) => (
      <>
        <DialogTitle variant="h3">Edit User(Info)</DialogTitle>
        <DialogContent
          sx={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}
        >
          {internalEditComponents}
          <Box>or render custom edit components here</Box>
        </DialogContent>
        <DialogActions>
          <MRT_EditActionButtons variant="text" table={table} row={row} />
        </DialogActions>
      </>
    ),
    // 行操作
    renderRowActions: ({ row, table }) => (
      <Box sx={{ display: 'flex', gap: '1rem' }}>
        <Tooltip title="Edit">
          <IconButton onClick={() => table.setEditingRow(row)}>
            <Edit />
          </IconButton>
        </Tooltip>
        <Tooltip title="Delete">
          <IconButton color="error" onClick={() => openDeleteConfirmModal(row)}>
            <Delete />
          </IconButton>
        </Tooltip>
      </Box>
    ),
    enableRowActions: true,
    enableRowSelection: true,// 允许行选择
    enableGrouping: false,
    enableHiding: true,
    enableSorting: true,
    // defaultColumn: {
    //   minSize: 40,
    //   maxSize: 1000,
    //   size: 180,
    // },

    // muiTableContainerProps: {
    //   sx: {
    //   },
    // },

    muiTableBodyProps: {
      sx: {
        maxHeight: isEnablePager ? '700px' || '600px' : 'unset',
        overflowY: 'auto',
        minHeight: '600px',
      },
    },
    muiTableBodyRowProps: ({ row }: any) => {
      let { original } = row;
      let custStyle: any = {};
      // if (original.moreLabRecordFound === true) {
      //   custStyle.background = '#F7EAC1';
      // }
      // if (original.moreLabRecordFound === false) {
      //   custStyle.background = '#FFC4C4';
      // }
      return {
        sx: { ...custStyle },
        className: '',
      };
    },
    // muiTableBodyRowProps: muiTableBodyRowProps,

    muiTableBodyCellProps: ({ cell, column, table }) => ({
      onClick: () => {
        table.setEditingCell(cell); //set editing cell
        //optionally, focus the text field
        queueMicrotask(() => {
          const textField = table.refs.editInputRefs.current[column.id];
          if (textField) {
            textField.focus();
            textField.select?.();
          }
        });
      },
    }),
    renderTopToolbarCustomActions: () => (
      <Box className="m-r-10 table_top_left">
        <Box className="flex flex-1">
          <Button
            onClick={() => {
              table.setCreatingRow(true); //simplest way to open the create row modal with no default values
              //or you can pass in a row object to set default values with the `createRow` helper function
              // table.setCreatingRow(
              //   createRow(table, {
              //     //optionally pass in default values for the new row, useful for nested data or other complex scenarios
              //   }),
              // );
            }}
          >
            Create New User
          </Button>
          {props.leftForm ?? " "}
        </Box>
      </Box>
    ),
    renderToolbarInternalActions: ({ table }) => {
      return (
        <>
          <Box className="visibleNotPrinter">
            <TextField
              name="searchCondition"
              onChange={(e: any) => {
                setGlobalFilter(e.target.value || '');
              }}
              value={globalFilter}
              autoComplete="off"
              InputProps={{
                startAdornment: (
                  <InputAdornment position="start">
                    <Search
                      onClick={() => {
                        setLoadTime(new Date());
                      }}
                      sx={{ cursor: 'pointer' }}
                    />
                  </InputAdornment>
                ),
                endAdornment: (
                  <InputAdornment position="start">
                    <Clear
                      onClick={() => {
                        setGlobalFilter('');
                      }}
                      sx={{ cursor: 'pointer' }}
                    />
                  </InputAdornment>
                ),
              }}
            />
          </Box>
        </>
      );
    },
    // muiBottomToolbarProps: {
    //   sx: {
    //     // display: "inline-block",
    //     display: "flex",
    //     width: "100%",
    //   },
    // },

    muiTableFooterCellProps: {
      sx: {
        display: 'flex',
        width: '45%',
        float: 'right',
      },
    },

    // renderBottomToolbarCustomActions: () => (
    //   <Box className="f-r f-s-14">
    //     <span className="total_counts">Total {rowCount} Records</span>
    //   </Box>
    // ),

    renderBottomToolbar: () => (
      <Box sx={{
        display: 'flex',
        width: '100%',
        padding: '10px',
        justifyContent: 'space-between',
        alignItems: 'center',
      }}>
        <Box>
          <span  >Total {rowCount} Records</span>{' '}
        </Box>
        <Box sx={{ display: 'flex', justifyContent: 'center', alignContent: 'center' }}>
          <Box>
            <span >Rows Per Page:</span>
            <Select
              disabled={isLoading}
              value={pagination.pageSize}
              onChange={(event: any) => {
                setPagination({
                  ...pagination,
                  pageSize: event?.target?.value || 10,
                  pageIndex: frontPager ? 0 : 1
                });
                const pageCount = tablesData.length > 0
                  ? Math.ceil(tablesData.length / event?.target?.value || 10)
                  : 0;
                setTotalPage(pageCount);
              }}
            >
              {showRowsPage.map((pageItem: any, indexItem: number) => (
                <MenuItem key={indexItem} value={pageItem}>
                  {pageItem}
                </MenuItem>
              ))}
            </Select>
          </Box>
          <Pagination
            disabled={isLoading}
            showFirstButton
            showLastButton
            shape="rounded"
            page={pagination.pageIndex + (frontPager ? 1 : 0)}
            count={totalPage} sx={{ display: 'flex', justifyContent: 'center', alignContent: 'center', marginRight: '20px' }}
            onChange={(event: any, page: number) => {
              setPagination({
                ...pagination,
                pageIndex: (frontPager ? -1 : 0) + page
              });
            }}
          />
        </Box>
      </Box>
    ),

    muiToolbarAlertBannerProps: isError
      ? {
        color: 'error',
        children: loadingErrorMessage,
      }
      : undefined,
  });

  return <MaterialReactTable table={table} />;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值