React-admin Datagrid:默认展开所有行

时间:2021-04-01 01:49:03

标签: reactjs datagrid material-ui react-admin

我有一个使用 List 的 react-admin (3.14.1) Datagrid,其中每一行都是可展开的。

有谁知道如何默认展开所有行

还是以编程方式展开一行?

我已经检查了 node_modules/ra-ui-materialui/lib/list/datagrid/Datagrid.js 中的 Datagrid 代码,没有明显的道具...

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

2 个答案:

答案 0 :(得分:1)

我有一个解决方案可以做类似的事情,而不是使用 jquery。这是一个自定义钩子,它使资源的第一个 id 展开,在我的例子中是列表中的第一项。

// useExpandFirst.ts

import * as React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Identifier, ReduxState, toggleListItemExpand } from 'react-admin';

type AboutExpansion = { noneExpanded: boolean; firstId: Identifier };

const useExpandFirst = (props) => {
  const { resource } = props;
  const once = React.useRef(false);

  const dispatch = useDispatch();
  const { noneExpanded, firstId } = useSelector<ReduxState, AboutExpansion>((state) => {
    const list = state?.admin?.resources?.[resource]?.list;

    return {
      noneExpanded: list?.expanded?.length === 0,
      firstId: list?.ids[0],
    };
  });

  React.useEffect(() => {
    if (noneExpanded && firstId && !once.current) {
      once.current = true;
      const action = toggleListItemExpand(resource, firstId);
      dispatch(action);
    }
  }, [noneExpanded, firstId, dispatch, resource]);
};

我没有在实际呈现列表的组件中使用钩子,而是在其他一些(并非如此)随机组件中使用它,例如应用程序的布局。这会导致呈现 List 的组件的重新呈现更少。

// MyLayout.tsx

const MyLayout: React.FC<LayoutProps> = (props) => {
  // expand the first company record as soon as it becomes available
  useExpandFirst({ resource: 'companies' });

  return (
    <Layout
      {...props}
      appBar={MyAppBar}
      sidebar={MySidebar}
      menu={MyMenu}
      // notification={MyNotification}
    />
  );
};

它并不完美,但可以胜任。只需进行一些修改,您就可以更改它以扩展所有 id。这意味着您必须为每个 id 分派操作(在 useEffect 钩子函数中)。

答案 1 :(得分:0)

用 jquery 破解它,亲爱的。

import $ from 'jquery'
import React, {Fragment} from 'react';
import {List, Datagrid, TextField, useRecordContext} from 'react-admin';

export class MyList extends React.Component {

    gridref = React.createRef()

    ensureRowsExpanded(ref) {
        // Must wait a tick for the expand buttons to be completely built
        setTimeout(() => {
            if (!ref || !ref.current) return;

            const buttonSelector = "tr > td:first-child > div[aria-expanded=false]"
            const buttons = $(buttonSelector, ref.current)
            buttons.click()
        }, 1)
    }

    /** 
     * This runs every time something changes significantly in the list,
     * e.g. search, filter, pagination changes.
     * Surely there's a better way to do it, i don't know!
    */
    Aside = () => {
        this.ensureRowsExpanded(this.gridref)
        return null;
    }

    render = () => {
        return <List {...this.props} aside={<this.Aside/>} >
                    <Datagrid 
                        expand={<MyExpandedRow />}
                        isRowExpandable={row => true}  
                        ref={this.gridref}
                    >
                        <TitleField source="title" />
                    </Datagrid>
               </List>
    }
}

const MyExpandedRow = () => {
    const record = useRecordContext();
    if (!record) return "";
    return <div>Hello from {record.id}</div>;
}

依赖于特定的表结构和 aria-expanded 属性,所以不是很好。虽然有效。