有什么方法可以自定义datagrid的表头?

问题描述

我正在使用react-admin 3.8.1

和我正在研究customize的表头以在下面实现-UDI密钥

enter image description here

我发现的是

const MyDatagridRow = ({ record,resource,id,onToggleItem,children,selected,basePath }) => (
    <TableRow key={id}>
        {/* first column: selection checkBox */}
        <TableCell padding="none">
            <CheckBox
                disabled={record.selectable}
                checked={selected}
                onClick={() => onToggleItem(id)}
            />
        </TableCell>
        {/* data columns based on children */}
        {React.Children.map(children,field => (
            <TableCell key={`${id}-${field.props.source}`}>
                {React.cloneElement(field,{
                    record,basePath,})}
            </TableCell>
        ))}
    </TableRow>
);

const MyDatagridBody = props => <DatagridBody {...props} row={<MyDatagridRow />} />;
const MyDatagrid = props => <Datagrid {...props} body={<MyDatagridBody />} />;

const PostList = props => (
    <List {...props}>
        <MyDatagrid>
            <TextField source="title" />
            ...
        </MyDatagrid>
    </List>
)

但是通过这种方式,我只能自定义数据网格的主体,而不能自定义表头。

目前,唯一的方法似乎是更改Datagrid.tsx,但我不想这样做。

如果有人知道解决方案。请让我知道谢谢。

解决方法

反应管理员的<Datagrid>没有提供自定义表格标题的方法。除了使用自己的<Datagrid>组件,您将没有其他解决方案。

您可以将以下代码作为基础(从react-admin源复制,并从TS迁移到JS):

import * as React from 'react';
import {
    isValidElement,Children,cloneElement,useCallback,FC,ReactElement,} from 'react';
import PropTypes from 'prop-types';
import {
    Checkbox,Table,TableProps,TableCell,TableHead,TableRow,} from '@material-ui/core';
import classnames from 'classnames';

import {
    sanitizeListRestProps,useListContext,useVersion,DatagridHeaderCell,DatagridLoading,DatagridBody,useDatagridStyles
} from 'react-admin';

/**
 * The Datagrid component renders a list of records as a table.
 * It is usually used as a child of the <List> and <ReferenceManyField> components.
 *
 * Props:
 *  - rowStyle
 *
 * @example Display all posts as a datagrid
 * const postRowStyle = (record,index) => ({
 *     backgroundColor: record.nb_views >= 500 ? '#efe' : 'white',* });
 * export const PostList = (props) => (
 *     <List {...props}>
 *         <Datagrid rowStyle={postRowStyle}>
 *             <TextField source="id" />
 *             <TextField source="title" />
 *             <TextField source="body" />
 *             <EditButton />
 *         </Datagrid>
 *     </List>
 * );
 *
 * @example Display all the comments of the current post as a datagrid
 * <ReferenceManyField reference="comments" target="post_id">
 *     <Datagrid>
 *         <TextField source="id" />
 *         <TextField source="body" />
 *         <DateField source="created_at" />
 *         <EditButton />
 *     </Datagrid>
 * </ReferenceManyField>
 */
const Datagrid = props => {
    const classes = useDatagridStyles(props);
    const {
        body = <DatagridBody />,children,classes: classesOverride,className,expand,hasBulkActions = false,hover,isRowSelectable,rowClick,rowStyle,size = 'small',...rest
    } = props;

    const {
        basePath,currentSort,data,ids,loaded,onSelect,onToggleItem,resource,selectedIds,setSort,total,} = useListContext(props);
    const version = useVersion();

    const updateSort = useCallback(
        event => {
            event.stopPropagation();
            const newField = event.currentTarget.dataset.field;
            const newOrder =
                currentSort.field === newField
                    ? currentSort.order === 'ASC'
                        ? 'DESC'
                        : 'ASC'
                    : event.currentTarget.dataset.order;

            setSort(newField,newOrder);
        },[currentSort.field,currentSort.order,setSort]
    );

    const handleSelectAll = useCallback(
        event => {
            if (event.target.checked) {
                const all = ids.concat(
                    selectedIds.filter(id => !ids.includes(id))
                );
                onSelect(
                    isRowSelectable
                        ? all.filter(id => isRowSelectable(data[id]))
                        : all
                );
            } else {
                onSelect([]);
            }
        },[data,selectedIds]
    );

    /**
     * if loaded is false,the list displays for the first time,and the dataProvider hasn't answered yet
     * if loaded is true,the data for the list has at least been returned once by the dataProvider
     * if loaded is undefined,the Datagrid parent doesn't track loading state (e.g. ReferenceArrayField)
     */
    if (loaded === false) {
        return (
            <DatagridLoading
                classes={classes}
                className={className}
                expand={expand}
                hasBulkActions={hasBulkActions}
                nbChildren={React.Children.count(children)}
                size={size}
            />
        );
    }

    /**
     * Once loaded,the data for the list may be empty. Instead of
     * displaying the table header with zero data rows,* the datagrid displays nothing in this case.
     */
    if (loaded && (ids.length === 0 || total === 0)) {
        return null;
    }

    const all = isRowSelectable
        ? ids.filter(id => isRowSelectable(data[id]))
        : ids;

    /**
     * After the initial load,if the data for the list isn't empty,* and even if the data is refreshing (e.g. after a filter change),* the datagrid displays the current data.
     */
    return (
        <Table
            className={classnames(classes.table,className)}
            size={size}
            {...sanitizeListRestProps(rest)}
        >
            <TableHead className={classes.thead}>
                <TableRow
                    className={classnames(classes.row,classes.headerRow)}
                >
                    {expand && (
                        <TableCell
                            padding="none"
                            className={classnames(
                                classes.headerCell,classes.expandHeader
                            )}
                        />
                    )}
                    {hasBulkActions && (
                        <TableCell
                            padding="checkbox"
                            className={classes.headerCell}
                        >
                            <Checkbox
                                className="select-all"
                                color="primary"
                                checked={
                                    selectedIds.length > 0 &&
                                    all.length > 0 &&
                                    all.every(id => selectedIds.includes(id))
                                }
                                onChange={handleSelectAll}
                            />
                        </TableCell>
                    )}
                    {Children.map(children,(field,index) =>
                        isValidElement(field) ? (
                            <DatagridHeaderCell
                                className={classes.headerCell}
                                currentSort={currentSort}
                                field={field}
                                isSorting={
                                    currentSort.field ===
                                    (field.props.sortBy ||field.props.source)
                                }
                                key={field.props.source || index}
                                resource={resource}
                                updateSort={updateSort}
                            />
                        ) : null
                    )}
                </TableRow>
            </TableHead>
            {cloneElement(
                body,{
                    basePath,className: classes.tbody,classes,hasBulkActions,version,},children
            )}
        </Table>
    );
};

Datagrid.propTypes = {
    basePath: PropTypes.string,body: PropTypes.element,children: PropTypes.node.isRequired,classes: PropTypes.object,className: PropTypes.string,currentSort: PropTypes.shape({
        field: PropTypes.string,order: PropTypes.string,}),data: PropTypes.object,// @ts-ignore
    expand: PropTypes.oneOfType([PropTypes.element,PropTypes.elementType]),hasBulkActions: PropTypes.bool,hover: PropTypes.bool,ids: PropTypes.arrayOf(PropTypes.any),loading: PropTypes.bool,onSelect: PropTypes.func,onToggleItem: PropTypes.func,resource: PropTypes.string,rowClick: PropTypes.oneOfType([PropTypes.string,PropTypes.func]),rowStyle: PropTypes.func,selectedIds: PropTypes.arrayOf(PropTypes.any),setSort: PropTypes.func,total: PropTypes.number,version: PropTypes.number,isRowSelectable: PropTypes.func,};

export default Datagrid;