Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use <List /> on React-Admin dashboard

Tags:

react-admin

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

like image 731
Thomas Halwax Avatar asked Sep 24 '18 20:09

Thomas Halwax


People also ask

How do I filter list in react-admin?

React-admin uses the filter query parameter from the URL to determine the filters to apply to the list. To change the filters, react-admin simply changes this filter query parameter, and the <List> components fetches dataProvider. getList() again with the new filters.

How customizable is react-admin?

React-admin components use the material-ui theming mechanism to define their appearance. This mechanism allows to reference a specific component by its style name (such as MuiButton for material-ui buttons) and override parts of its styles. Almost all components provided by react-admin are customizable this way.

Does react-admin use Redux?

The most important difference between react-admin v3 and v4 lies under the hood. React-admin v4 no longer uses Redux for state management - without changing the developer API.


2 Answers

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.

like image 145
Thomas Halwax Avatar answered Nov 16 '22 03:11

Thomas Halwax


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://stackoverflow.com/a/8649003/1501205
            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

like image 27
Michail Michailidis Avatar answered Nov 16 '22 04:11

Michail Michailidis