Use <List /> on React-Admin dashboard
Asked Answered
I

6

8

I'm using react-admin v2.3.2 with a custom dashboard component as shown in the react-admin tutorial.

    <Admin dashboard={MyDashboard}>
       <Resource name="incidents ... />
    </Admin>

Now I'd like to display a list of incidents on my dashboard using the component of react-admin but react-admin complains about missing properties like 'hasEdit'.

I simply passed the props of the dashboard component to the List but this does obviously not work:

    class MyDashboard extends React.Component    {
      constructor(props) {
      super(props)

      render(
        return <List {...this.props}>
          <Datagrid> .... </Datagrid>
        </List>

      )
    }

Is it possible to use react-admin's <List /> component on the dashboard and if so how can this be done?

Thanks in advance, Thomas

Integrant answered 24/9, 2018 at 20:59 Comment(0)
I
10

I finally managed to use react-admin's components by faking the required props. Within the MyDashboard component I define props required by the component:

    let fakeProps = {
        basePath: "/incidents",
        hasCreate: false,
        hasEdit: false,
        hasList: true,
        hasShow: false,
        history: {},
        location: { pathname: "/", search: "", hash: "", state: undefined },
        match: { path: "/", url: "/", isExact: true, params: {} },
        options: {},
        permissions: null,
        resource: "incidents"
    }

    <List {...fakeProps}>
      <DataGrid>
        <TextField .... />
      </DataGrid>
    </List>

This is indeed a sub-optimal solution but in the first run it solves my problem.

Integrant answered 27/9, 2018 at 19:21 Comment(5)
I have the same issue. I solved showing the core stuff the same way you did here(though you don't need all the fake props for it to work). My problem is I I want pagination and filter capability. I am able to put a list on that page, but when I sort/filter/search/ or change pages, it redirects to the CRUD list instead of staying on the dashboard. So my question is - How can I disable the redirect?Metrology
@WilliamSchroederMcKinley check my solution for pagination - it should be easy to add the filtering update too on dashboard :)Azores
@Thomas Halwax how to implement custom api load into list and datagrid.please help me.my url like this localhost:3000/api/templates/…Leila
@Leila I'm sorry but your question is not very specific. Please create a new question and add more details.Integrant
@ThomasHalwax pls check my question once #55371179Leila
A
1

We had a request to create a List in the Dashboard so I had use the accepted answer. Though pagination wouldn't trigger new requests to the server even though the url was changing.

This is the final solution that works with pagination using react-router v4.

In <Admin dashboard={Dashboard}> I added:

<Resource name="dashboard-stats"/>

In the Dashboard.js this is what I have:

import React, { Component } from 'react';
import { GET_LIST } from 'react-admin';
import Card from '@material-ui/core/Card';
import CardHeader from '@material-ui/core/CardHeader';

import dataProvider from './dataProvider';
import {
    List,
    TextField,
    Datagrid
} from 'react-admin';


export default class Dashboard extends Component {
    state = {};

    initProps = {
        basePath: "/",
        hasCreate: false,
        hasEdit: false,
        hasList: true,
        hasShow: false,
        location: { pathname: "/", search: "", hash: "", state: undefined },
        match: { path: "/", url: "/", isExact: true, params: {} },
        options: {
        },
        permissions: null,
        resource: "dashboard-stats",
        perPage: 5
    };

    componentWillMount() {
        this.unlisten = this.props.history.listen((location, action) => {

        if (location.search) {
            //regex from: https://mcmap.net/q/79952/-how-to-convert-url-parameters-to-a-javascript-object-duplicate
            let queryParams = JSON.parse('{"' + decodeURI(location.search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}')
            let perPage = queryParams.perPage;
            let page = queryParams.page;
            this.initProps.perPage = perPage;
            this.initProps.page = page;
            this.initProps.location = location;
            this.setState({'initProps': this.initProps})

            }

        });
    }
    componentWillUnmount() {
        this.unlisten();
    }


    componentDidMount() {

        this.setState({'initProps': this.initProps});

        dataProvider(GET_LIST, 'stats', {
            sort: { field: 'date', order: 'DESC' },
            pagination: { page: 1, perPage: 50 },
        })
        .then(response => {
            this.setState({'stats':  response.data});
        });
    }

    render() {

        const {
            initProps
        } = this.state;

        if(!initProps) {
            return false;
        }


        return <Card>
            <CardHeader title="Welcome to the Dashboard" />


            <List {...initProps} >
                    <Datagrid>
                        <TextField source="description" />
                        <TextField source="state" />
                        <TextField source="date" />
                    </Datagrid>
                </List>

        </Card>;

    }
}

don't forget to update the location this.initProps.location with the location just changed - otherwise it will work for the first click (route change) and then it will stop working

Azores answered 8/2, 2019 at 16:58 Comment(1)
I have the same requirement. It looks like react-admin is not very flexible in this regard. Has anyone tried to use ListController directly?Bidget
H
1

I came across this page researching similar. The way to do this now (late 2020) is to create a ListContextProvider on the page for the main resource you want to show on the dashboard so you get everything provided by that context, including filters.

const controllerProps = useListController(props);
  
<ListContextProvider value={controllerProps}>
  <MyDashboardView>
</ListContextProvider>
Hawkinson answered 24/11, 2020 at 19:36 Comment(0)
R
0

You must be wanting to display data from various resources, otherwise you would just use a regular "List" page.

Dashboard can do this. Have a look at the Demo Dashboard

Multiple dataProvider(GET_LIST,... that you pass on to components. You can use this Demo Dashboard Component as an example. Pending Orders

Rhizotomy answered 25/9, 2018 at 1:18 Comment(1)
You are right, I'd like to show the most recent/important data from multiple resources. The demo Dashboard is crafted manually, without any 'magic' of react-admin. To be more specific: my question is if it is possible to use the 'magic' components (like List, Datagrid, TextField, ...) from react-admin in order to get all the benefits like filters, sorting, ...Integrant
S
0

Thanks for the solution. Screen renders with below warning

How to remove all warnings ? Warning: React does not recognize the basePath prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase basepath instead. If you accidentally passed it from a parent component, remove it from the DOM element.

Like basePath console shows same warnings with other props "currentSort, defaultTitle, displayedFilters,filterValues,hasCreate,hideFilter,isLoading,loadedOnce,onToggleItem,onUnselectItems,perPage,selectedIds,setFilters,setPage,setPerPage,setSort,showFilter,hasBulkActions"

Warning: Invalid value for prop translate on tag. Either remove it from the element, or pass a string or number value to keep it in the DOM. For details

const initProps = {
  basePath: '/',
  hasCreate: false,
  hasEdit: false,
  hasList: true,
  hasShow: false,
  location: { pathname: '/', search: '', hash: '', state: undefined },
  match: { path: '/', url: '/', isExact: true, params: {} },
  options: {},
  permissions: null,
  resource: 'dashboard',
  perPage: 5
};

<List
{...initProps}
filterDefaultValues={{
  arrivedTimestampStart: moment().format('YYYY-MM-DD'),
  arrivedTimestamp: moment().format('YYYY-MM-DD')
}}
filters={<DashboardFilter />}
sort={{ field: 'arrivedTimestamp', order: 'DESC' }}
pagination={<Fragment />}
exporter={false}
>
<Responsive
  medium={
    <div style={styles.flex}>
     <OtherComponent />
    </div>
    }
/>
</List>
Schuler answered 18/11, 2019 at 11:21 Comment(1)
@Michail Michailidis Can you please help ?Schuler
C
0

I think the answer in v4+ is now the useList hook, which you can see on the List docs page: https://marmelab.com/react-admin/List.html. Copied from that page:

const data = [
    { id: 1, name: 'Arnold' },
    { id: 2, name: 'Sylvester' },
    { id: 3, name: 'Jean-Claude' },
]
const ids = [1, 2, 3];

const MyComponent = () => {
    const listContext = useList({
        data,
        ids,
        basePath: '/resource',
        resource: 'resource',
    });
    return (
        <ListContextProvider value={listContext}>
            <Datagrid>
                <TextField source="id" />
                <TextField source="name" />
            </Datagrid>
        </ListContextProvider>
    );
};
Cataldo answered 6/3, 2022 at 11:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.