简体   繁体   English

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

[英]React-admin Datagrid: expand all rows by default

I have a react-admin (3.14.1) List using a Datagrid , where each row is expandable.我有一个使用Datagrid的 react-admin (3.14.1) List ,其中每一行都是可扩展的。

Does anyone know how to expand all the rows by default ?有谁知道如何默认扩展所有行

Or expand a row programmatically?或者以编程方式扩展一行?

I've checked the Datagrid code in node_modules/ra-ui-materialui/lib/list/datagrid/Datagrid.js , no obvious props...我检查了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,
};

I have a solution that does something similar, not using jquery.我有一个类似的解决方案,不使用 jquery。 It's a custom hook that makes the first id of a resource expand, which in my case is the first item in the List.这是一个自定义钩子,它使资源的第一个 id 展开,在我的例子中,它是 List 中的第一个项目。

// 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]);
};

Instead of using the hook in the component that actually renders the List, I'm using it in some other (not so) random component, for example the app's Layout.我没有在实际呈现列表的组件中使用钩子,而是在其他一些(不是这样)随机组件中使用它,例如应用程序的布局。 That causes way less rerenders of the component that renders the 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}
    />
  );
};

It's not perfect, but it does the job.它并不完美,但它可以完成工作。 With just a few modifications, you can alter it to expand all id's.只需进行一些修改,您就可以对其进行更改以扩展所有 id。 That would mean that you have to dispatch the action for each id (in the useEffect hook function).这意味着您必须为每个 id 调度操作(在 useEffect 挂钩函数中)。

Hacked it with jquery, dear dear.用 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>;
}

Relies on particular table structure and aria-expanded attribute, so not great.依赖于特定的表结构和aria-expanded属性,所以不是很好。 Works though.虽然有效。

I found this question and used this answer to solve the same problem.我发现了这个问题并用这个答案解决了同样的问题。

export const useExpandDefaultForAll = (resource) => {
    const [ids, expanded]  = useSelector(
        (state) => ([state.admin.resources[resource].list.ids, state.admin.resources[resource].list.expanded])
    );
    const dispatch = useDispatch();
    useEffect(() => {
        for (let i = 0; i < ids.length; i++) {
            if (!expanded.includes(ids[i])){
                dispatch(toggleListItemExpand(resource, ids[i]));
            }
        }
    }, [ids]);
};

And i also call it in my List component:我也在我的List组件中调用它:

const OrderList = (props) => {
    useExpandDefaultForAll(props.resource);
... 

I will be glad if it is useful to someone.如果它对某人有用,我会很高兴。 If you know how to do it better then please fix it.如果您知道如何做得更好,请修复它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM