Материал Ui Table Sort with pagination - PullRequest
6 голосов
/ 19 июня 2020

Я пытаюсь настроить свою таблицу для сортировки по различным столбцам, следуя документации пользовательского интерфейса материала. Я не уверен, почему он не работает, но при нажатии на заголовок появляется порядок сортировки, и я вижу, что все запускает его, но не сортирует. Я считаю, что где-то в моем коде есть крошечная ошибка, и, глядя на нее в течение нескольких часов, я не могу ее найти.

Документация по таблице пользовательского интерфейса материала

Рабочий код Sandbox I Я также пытаюсь следовать, что соответствует документации: CodeSandbox

База кода:

function TablePaginationActions(props) {
    const theme = useTheme();
    const { count, page, rowsPerPage, onChangePage } = props;

    const handleFirstPageButtonClick = (event) => {
        onChangePage(event, 0);
    };

    const handleBackButtonClick = (event) => {
        onChangePage(event, page - 1);
    };

    const handleNextButtonClick = (event) => {
        onChangePage(event, page + 1);
    };

    const handleLastPageButtonClick = (event) => {
        onChangePage(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
    };

    return (
        <div style={{ flexShrink: 0 }}>
            <IconButton
                onClick={handleFirstPageButtonClick}
                disabled={page === 0}
                aria-label="first page"
            >
                {theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
            </IconButton>
            <IconButton onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
                {theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
            </IconButton>
            <IconButton
                onClick={handleNextButtonClick}
                disabled={page >= Math.ceil(count / rowsPerPage) - 1}
                aria-label="next page"
            >
                {theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
            </IconButton>
            <IconButton
                onClick={handleLastPageButtonClick}
                disabled={page >= Math.ceil(count / rowsPerPage) - 1}
                aria-label="last page"
            >
                {theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
            </IconButton>
        </div>
    );
}

TablePaginationActions.propTypes = {
    count: PropTypes.number.isRequired,
    onChangePage: PropTypes.func.isRequired,
    page: PropTypes.number.isRequired,
    rowsPerPage: PropTypes.number.isRequired,
};

function descendingComparator(a, b, orderBy) {
  if (b[orderBy] < a[orderBy]) {
    return -1;
  }
  if (b[orderBy] > a[orderBy]) {
    return 1;
  }
  return 0;
}

function getComparator(order, orderBy) {
  return order === "desc"
    ? (a, b) => descendingComparator(a, b, orderBy)
    : (a, b) => -descendingComparator(a, b, orderBy);
}

function stableSort(array, comparator) {
  const stabilizedThis = array.map((el, index) => [el, index]);
  stabilizedThis.sort((a, b) => {
    const order = comparator(a[0], b[0]);
    if (order !== 0) return order;
    return a[1] - b[1];
  });
  return stabilizedThis.map(el => el[0]);
}

const headCells = [
  {
    id: "",
    numeric: false,
    disablePadding: true,
    label: ""
  },
  { id: "Holiday", numeric: true, disablePadding: false, label: "Holiday" },
  { id: "Date", numeric: true, disablePadding: false, label: "Date" },
  { id: "Branch", numeric: true, disablePadding: false, label: "Branch" },
  { id: "Hours", numeric: true, disablePadding: false, label: "Hours" },
  { id: "Web", numeric: true, disablePadding: false, label: "Web" },
  { id: "Phone", numeric: true, disablePadding: false, label: "Phone" },
  { id: "CoOp", numeric: true, disablePadding: false, label: "CoOp" },
  { id: "Submitted", numeric: true, disablePadding: false, label: "Submitted" },
  { id: "SubmittedBy", numeric: true, disablePadding: false, label: "SubmittedBy" },
  { id: "Published", numeric: true, disablePadding: false, label: "Published" },
  { id: "PublishedBy", numeric: true, disablePadding: false, label: "PublishedBy" },
];

const useStyles = makeStyles(theme => ({
  visuallyHidden: {
    border: 0,
    clip: "rect(0 0 0 0)",
    height: 1,
    margin: -1,
    overflow: "hidden",
    padding: 0,
    position: "absolute",
    top: 20,
    width: 1
  }
}));

function EnhancedTableHead(props) {
  const {
    classes,
    order,
    orderBy,
    onRequestSort
  } = props;
  const createSortHandler = property => event => {
    onRequestSort(event, property);
  };

  return (
    <TableHead>
      <TableRow>
        {headCells.map(headCell => (
          <TableCell
            key={headCell.id}
            sortDirection={orderBy === headCell.id ? order : false}
          >
            <TableSortLabel
              active={orderBy === headCell.id}
              direction={orderBy === headCell.id ? order : "asc"}
              onClick={createSortHandler(headCell.id)}
            >
              {headCell.label}
              {orderBy === headCell.id ? (
                <span className={classes.visuallyHidden}>
                  {order === "desc" ? "sorted descending" : "sorted ascending"}
                </span>
              ) : null}
            </TableSortLabel>
          </TableCell>
        ))}
      </TableRow>
    </TableHead>
  );
}

const HolidaySettings = () => {
    const classes = useStyles();
    const [loading, setLoading] = useState(true);
    const [open, setOpen] = React.useState(false);
    const [page, setPage] = React.useState(0);
    const [rowsPerPage, setRowsPerPage] = React.useState(5);
    const anchorRef = React.useRef(null);
    const [dialogOpen, setDialogOpen] = React.useState(false);
    const [dialogData, setDialogData] = React.useState({});
    const [showInactive, setShowInactive] = useState(false);
    const [searchResults, setSearchResults] = useState([]);
    const [order, setOrder] = React.useState("asc");
    const [orderBy, setOrderBy] = React.useState("Holiday");

    const dispatch = useDispatch();

    const onInit = useCallback(() => {
        dispatch(actions.holiday_getHolidays());
        dispatch(actions.holiday_getProductionHolidays());
    }, [dispatch]);

    useEffect(() => {
        if (loading) {
            onInit();
        }
    }, [loading]);

    const rows = useSelector(state => {
        let results = [];

        if (showInactive) {
            results = state.holidays.holidays;
        } else {            
            results = state.holidays.activeHolidays;
        }

        if (state.holidays.holidays && loading) {
            setLoading(false);
            setSearchResults(results);
        }

        return results;
    });

    const handleRequestSort = (event, property) => {
        const isAsc = orderBy === property && order === "asc";
        setOrder(isAsc ? "desc" : "asc");
        setOrderBy(property);
    };

    const handleToggle = () => {
        setOpen((prevOpen) => !prevOpen);
    };

    const handleDialogOpen = (dataElement) => {
        setDialogData(dataElement);
        setDialogOpen(true);
        setOpen(false);
    }

    const handleHolidayDelete = (dataElement) => {
        dispatch(actions.holiday_deleteHoliday(dataElement));
    }

    const handleDialogClose = () => {
        setOpen(false);
        setDialogOpen(false);
    };

    const handleClose = (event) => {
        if (anchorRef.current && anchorRef.current.contains(event.target)) {
            return;
        }

        setOpen(false);
    };

    const handleChangePage = (event, newPage) => {
        setPage(newPage);
    };

    const handleChangeRowsPerPage = (event) => {
        setRowsPerPage(parseInt(event.target.value, 10));
        setPage(0);
    };

    const handleInactiveChange = (e) => {
        e.persist();
        const { checked } = e.target;
        setShowInactive(checked)
    }

    const handleSearch = (e) => {
        e.persist();
        const searchValue = e.target.value;
        let results = _.map(rows, function(holiday) {
            if (holiday.HolidayName.toLowerCase().indexOf(searchValue.toLowerCase()) !== -1) return holiday;
        });
        results = _.without(results, undefined);
        setSearchResults(results);
    }



    return (
        <div>
            <div className="row">
                <div className="col">
                    <div className="card-chart card">
                        <div className="card-header">
                            <div className="row">
                                <div className="col-sm-12 d-flex">
                                    <h4 className="card-title">Holiday Settings</h4>

                                    <div
                                        className="ml-auto mr-5"
                                        ref={anchorRef}
                                        aria-controls={open ? 'menu-list-grow' : undefined}
                                        aria-haspopup="true"
                                        onClick={handleToggle}>
                                        <SettingsOutlinedIcon style={{ fontSize: 20 }} />
                                        {open ? (
                                            <ExpandLess style={{ fontSize: 12 }} />
                                        ) : (
                                                <ExpandMore style={{ fontSize: 12 }} />
                                            )}
                                    </div>
                                    <Popper open={open} anchorEl={anchorRef.current} role={undefined} transition disablePortal>
                                        {({ TransitionProps, placement }) => (
                                            <Grow
                                                {...TransitionProps}
                                                style={{ transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' }}
                                            >
                                                <Paper>
                                                    <ClickAwayListener onClickAway={handleClose}>
                                                        <MenuList autoFocusItem={open} id="menu-list-grow">
                                                            <MenuItem onClick={handleDialogOpen}>Add Holiday</MenuItem>
                                                            <MenuItem>
                                                                <FormControlLabel className=""
                                                                    label="Show Inactive"
                                                                    control={
                                                                        <Checkbox
                                                                            checked={showInactive || false}
                                                                            value={showInactive}
                                                                            onChange={handleInactiveChange}
                                                                            name="Show Inactive"
                                                                            color="primary"
                                                                        />
                                                                    }
                                                                />
                                                            </MenuItem>
                                                        </MenuList>
                                                    </ClickAwayListener>
                                                </Paper>
                                            </Grow>
                                        )}
                                    </Popper>
                                </div>
                            </div>
                        </div>
                        {loading ? (
                            <CanvasLoader loading={loading} />
                        ) : (
                                <div className="card-body">
                                    <div className="text-left col-12">
                                        <Paper>
                                            <TextField id="standard-basic" label="Search" onChange={handleSearch}/>
                                            <TableContainer component={Paper} className="holidaysTableContainer">
                                                <Table className="w-100" aria-label="simple table">
                                                    <EnhancedTableHead
                                                      classes={classes}
                                                      order={order}
                                                      orderBy={orderBy}
                                                      onRequestSort={handleRequestSort}
                                                      rowCount={rows.length}
                                                    />
                                                    <TableBody>
                                                        {stableSort(searchResults, getComparator(order, orderBy))
                                                            .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                                                            .map((row, index) => {
                                                                return (
                                                                    <TableRow key={row.RowId} id={row.Id} className={row.Active ? '' : 'inactive-row'}>
                                                                        <TableCell>{<div className="d-flex flex-align-center justify-content-center"><CreateOutlinedIcon className="holidayEditIcon" style={{ color: '#00f2c3' }} onClick={() => { handleDialogOpen(row); }} /> {row.Active ? (<DeleteForeverOutlinedIcon className="holidayDeleteIcon" style={{ color: '#fd5d93' }} onClick={() => { handleHolidayDelete(row); }} />) : (<div></div>)}</div>}</TableCell>
                                                                        <TableCell>{row.HolidayName}</TableCell>
                                                                        <TableCell>{moment(row.HolidayDate).format('ddd, MMM Do YYYY')}</TableCell>
                                                                        <TableCell>{row.Branch ? row.Branch : 'All'}</TableCell>
                                                                        <TableCell>{row.Hours ? row.Hours : 'Closed'}</TableCell>
                                                                        <TableCell>{(row.Web ? <DoneIcon style={{ color: '#00f2c3' }} value="true" /> : <CloseIcon style={{ color: '#fd5d93' }} value="false" />)}</TableCell>
                                                                        <TableCell>{(row.Phone ? <DoneIcon style={{ color: '#00f2c3' }} value="true" /> : <CloseIcon style={{ color: '#fd5d93' }} value="false" />)}</TableCell>
                                                                        <TableCell>{(row.CoOp ? <DoneIcon style={{ color: '#00f2c3' }} value="true" /> : <CloseIcon style={{ color: '#fd5d93' }} value="false" />)}</TableCell>
                                                                        <TableCell>{(row.Submitted ? moment(row.Submitted).format('MMM Do, YYYY') : false)}</TableCell>
                                                                        <TableCell>{row.SubmittedBy}</TableCell>
                                                                        <TableCell>{(row.Published ? moment(row.Published).format('MMM Do, YYYY') : false)}</TableCell>
                                                                        <TableCell>{row.PublishedBy}</TableCell>
                                                                    </TableRow>
                                                                )
                                                        })}
                                                    </TableBody>
                                                    <TableFooter>
                                                        <TableRow>
                                                            <TablePagination
                                                                rowsPerPageOptions={[5, 10, 25, { label: 'All', value: -1 }]}
                                                                colSpan={12}
                                                                count={searchResults.length}
                                                                rowsPerPage={rowsPerPage}
                                                                page={page}
                                                                onChangePage={handleChangePage}
                                                                onChangeRowsPerPage={handleChangeRowsPerPage}
                                                                ActionsComponent={TablePaginationActions}
                                                            />
                                                        </TableRow>
                                                    </TableFooter>
                                                </Table>
                                            </TableContainer>
                                        </Paper>
                                        <HolidayDialog open={dialogOpen} onClose={handleDialogClose} data={dialogData} />
                                    </div>
                                </div>
                            )} 
                    </div>
                </div>
            </div>
        </div>
    )
}

export default HolidaySettings;

1 Ответ

4 голосов
/ 28 июня 2020

Согласно вашему коду, TableHead и TableBody отображаются с разными идентификаторами.

  • Название праздника в TableHead имеет id = 'Holiday', но в TableBody это 'HolidayName'.

  • Дата праздника в TableHead имеет id = 'Date', а в TableBody это 'HolidayDate' .

Вы должны назначить аналогичную строку, как id, TableHead и TableBody.

Поэтому попробуйте следующие изменения в произвести сортировочные работы

const headCells = [
  {
    id: "",
    numeric: false,
    disablePadding: true,
    label: ""
  },
  { id: "HolidayName", numeric: true, disablePadding: false, label: "Holiday" },
  { id: "HolidayDate", numeric: true, disablePadding: false, label: "Date" },
  { id: "Branch", numeric: true, disablePadding: false, label: "Branch" },
  { id: "Hours", numeric: true, disablePadding: false, label: "Hours" },
  { id: "Web", numeric: true, disablePadding: false, label: "Web" },
  { id: "Phone", numeric: true, disablePadding: false, label: "Phone" },
  { id: "CoOp", numeric: true, disablePadding: false, label: "CoOp" },
  { id: "Submitted", numeric: true, disablePadding: false, label: "Submitted" },
  { id: "SubmittedBy", numeric: true, disablePadding: false, label: "SubmittedBy" },
  { id: "Published", numeric: true, disablePadding: false, label: "Published" },
  { id: "PublishedBy", numeric: true, disablePadding: false, label: "PublishedBy" },
];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...