implement BackButton in react-admin
Asked Answered
S

3

5

I need to implement a <BackButton /> in react-admin for example when I open show page for a resource I need able to back to the list page.

Can you guide me to implement this? I'm not familiar with react-admin routing mechanism. Now I'm using this component in my edit form actions props:

const MyActions = ({ basePath, data, resource }) => (
    <CardActions>
        <ShowButton basePath={basePath} record={data} />
        <CloneButton basePath={basePath} record={data} />
        {/* Need <BackButton /> here */}
    </CardActions>
);

export const BookEdit = (props) => (
    <Edit actions={<MyActions />} {...props}>
        <SimpleForm>
            ...
        </SimpleForm>
    </Edit>
);
Spacial answered 20/2, 2019 at 14:52 Comment(0)
A
8

You can use react-router-redux's goBack() function to achieve this.

For example, your button component will look something like this:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import Button from '@material-ui/core/Button';
import { goBack } from 'react-router-redux';

class BackButton extends Component {
    handleClick = () => {
        this.props.goBack();
    };

    render() {
        return <Button variant="contained" color="primary" onClick={this.handleClick}>Go Back</Button>;
    }
}

export default connect(null, {
    goBack,
})(BackButton);

Now use that button component in your CardActions.

You can get help from an example which uses react-router-redux's push() function in a similar way from the official docs.

Achorn answered 20/2, 2019 at 17:7 Comment(0)
B
4

Create a back button. This one will pass props and children (text) and uses react-router directly, which I think makes more sense and keeps your code simple.

// BackButton.js

import React from 'react'
import Button from '@material-ui/core/Button'
import { withRouter } from 'react-router'

const BackButton = ({ history: { goBack }, children, ...props }) => (
  <Button {...props} onClick={goBack}>
    {children}
  </Button>
)

export default withRouter(BackButton)

Example usage:

import { Toolbar, SaveButton } from 'react-admin'
import BackButton from './BackButton'

const SomeToolbar = props => (
  <Toolbar {...props}>
    <SaveButton />
    <BackButton
      variant='outlined'
      color='secondary'
      style={{ marginLeft: '1rem' }}
    >
      Cancel
    </BackButton>
  </Toolbar>
)
Busywork answered 12/6, 2020 at 9:28 Comment(0)
W
0

The complete code is below.

//BackButton.js

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import compose from 'recompose/compose';
import { withStyles, createStyles } from '@material-ui/core/styles';
import { translate } from 'ra-core';
import Button from '@material-ui/core/Button';
import ArrowBack from '@material-ui/icons/ArrowBack';
import classnames from 'classnames';
import { fade } from '@material-ui/core/styles/colorManipulator';

const styles = theme =>
    createStyles({
        deleteButton: {
            color: theme.palette.error.main,
            '&:hover': {
                backgroundColor: fade(theme.palette.error.main, 0.12),
                // Reset on mouse devices
                '@media (hover: none)': {
                    backgroundColor: 'transparent',
                },
            },
        },
    });

const sanitizeRestProps = ({
    basePath,
    className,
    classes,
    label,
    invalid,
    variant,
    translate,
    handleSubmit,
    handleSubmitWithRedirect,
    submitOnEnter,
    record,
    redirect,
    resource,
    locale,
    ...rest
}) => rest;

class BackButton extends Component {
  static contextTypes = {
    router: () => true, // replace with PropTypes.object if you use them
  }

  static propTypes = {
          label: PropTypes.string,
          refreshView: PropTypes.func.isRequired,
          icon: PropTypes.element,
      };

  static defaultProps = {
      label: 'ra.action.back',
      icon: <ArrowBack />,
  };

  render() {
    const {
                className,
                classes = {},
                invalid,
                label = 'ra.action.back',
                pristine,
                redirect,
                saving,
                submitOnEnter,
                translate,
                icon,
                onClick,
                ...rest
            } = this.props;
    return (
      <Button
            onClick={this.context.router.history.goBack}
            label={label}
            className={classnames(
                'ra-back-button',
                classes.backButton,
                className
            )}
            key="button"
            {...sanitizeRestProps(rest)}>
          {icon} {label && translate(label, { _: label })}
      </Button>
    )
  }
}

const enhance = compose(
    withStyles(styles),
    translate
);

export default enhance(BackButton);
//Toolbar.js

import React from 'react';
import {
    Toolbar,
    SaveButton,
    DeleteButton,
} from 'react-admin';

import { withStyles } from '@material-ui/core';
import BackButton from './BackButton'

const toolbarStyles = {
    toolbar: {
        display: 'flex',
        justifyContent: 'space-between',
    },
};

export const CustomEditToolbar = withStyles(toolbarStyles)(props => (
    <Toolbar {...props}>
        <SaveButton/>
        <DeleteButton/>
        <BackButton/>
    </Toolbar>
));

export const CustomCreateToolbar = withStyles(toolbarStyles)(props => (
    <Toolbar {...props}>
        <SaveButton/>
        <BackButton/>
    </Toolbar>
));
Wame answered 13/10, 2019 at 23:17 Comment(3)
To help the questioner include comments explaining the code you have produced. A big block of code might leave them just as confused.Sorb
Class components, or function components? Make up your mind and use a consistent standard. This looks cobbled together from two different places or authors, and isn't code I'd accept in a pull request.Chrismatory
Also, this (as the other items listed above) isn't syntactically-valid for those of us using TypeScript.Chrismatory

© 2022 - 2024 — McMap. All rights reserved.