Custom layout in SimpleForm component on react-admin
Asked Answered
N

3

7

I want to create a custom two-column-grid layout on my react-admin project on Edit and Show pages. I want to display selectboxes and the imageupload area on the left column, and the text inputs on the right column by using only one <SimpleForm>.

Simply like this

If I use a div or a <Card> component under <SimpleForm> and <EditController> components, I receive an error.

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.

Is there any way to create a layout without this error?

Neomaneomah answered 13/11, 2018 at 10:10 Comment(3)
It would be useful to see how you did in first place so we could see where the error came from.Group
Related GitHub issue for react-admin: github.com/marmelab/react-admin/issues/…Fungous
Does this answer your question? How do I have more complex layouts in `react-admin` "Show" and "Edit" and "Create" screens?Dredge
N
5

I solved it with creating another component with using divs, <Grid/> etc, and used that component in <SimpleForm> component.

import {withStyles} from '@material-ui/core/styles';
import React from 'react';
import {
    EditController,
    SimpleForm,
    TextInput,
    SelectInput,
    Title,
} from 'react-admin';
import Grid from '@material-ui/core/Grid';
import Card from '@material-ui/core/Card';
import Poster from "../customField/Poster";
import {EditToolbar} from '../toolbar/CustomToolbar'
import {EditActions} from '../toolbar/CustomActions'

const editStyles = {
    root: {display: 'flex', alignItems: 'flex-start', width: '100%'},
    form: {flexGrow: 9},
};


class CardEdit extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            refresh: false
        };
    }

    render() {
        const FormDiv = withStyles(editStyles)(({children, classes, ...props}) => {
                return (
                    <div className={classes.root}>
                        <div className={classes.form}>
                            <Grid container spacing={24}>
                                <Grid item xs={6}>
                                    <TextInput source="name" fullWidth />
                                </Grid>
                                <Grid item xs={6}>
                                    <TextInput source="card_id" fullWidth />
                                </Grid>
                            </Grid>
                        </div>
                        </div>
                )
            }
        )

        return (
        <EditController {...this.props}>
            {({resource, record, redirect, save, basePath, version}) => {
                return (
                <div>
                    <Title defaultTitle="sample"/>
                    <Card>
                        <div style={{ margin: '20px 20px 0 0' }}>
                            <EditActions
                                basePath={basePath}
                                resource={resource}
                                data={record}
                                hasShow
                                hasList
                            />
                        </div>
                        {record && (
                            <SimpleForm
                                basePath={basePath}
                                redirect={redirect}
                                resource={resource}
                                record={record}
                                save={save}
                                version={version}
                                toolbar={<EditToolbar/>}
                            >

                                <FormDiv record={record} />
                            </SimpleForm>
                        )}
                    </Card>
                </div>
            )
            }}
        </EditController>
        )
    }
}

export default withStyles(editStyles)(CardEdit);
Neomaneomah answered 15/11, 2018 at 3:11 Comment(2)
Could you post code about how you did that? I am also interested in this.Group
@GreenMagic I edited my comment by adding my Edit page code for you to have a reference.Neomaneomah
C
2

Actually, this could be done a little bit easier in case you don't need any custom styles and what not. In order to get rid of the basePath error, just sanitize the props passed to the Material UI Grid Component:

const SanitizedGrid = ({basePath, ...props}) => {
  return (
    <Grid {...props} />
  );
};

Then use it in place of a normal Grid:

export default props => (
  <SimpleForm {...props}>
    <SanitizedGrid container spacing={16}>
        <Grid item xs>
            <TextInput source="name" />
        </Grid>
    </SanitizedGrid>
  </SimpleForm>
);
Calcine answered 28/6, 2019 at 5:22 Comment(1)
In case it wasn't obvious at first glance, the key thing here is you're separating the "basePath" from the other "props" when defining "SanitizedGrid". That way when you pass {...props} to the "Grid" component, "basePath" doesn't come along.Fungous
C
1

As another way, I've just worked out (thanks to Alexander's answer) a nice generic way to add any custom HTML content to a react-admin form:

import React, { Fragment }      from 'react';
import { SimpleForm }           from 'react-admin';

const CustomContent = ({ basePath, record, resource, children }) => (
  <Fragment>
    {children}
  </Fragment>
);

export const MyForm = (props) => (
  <SimpleForm>
    <CustomContent>
      <h3>Custom Content</h3>
      <p>I can now add standard HTML to my react admin forms!</p>
    </customContent>
  </SimpleForm>
);

You get the basePath prop (which you probably don't want), but the record and resource props might be useful to your custom content (if you switch the code to use a render prop)

Clemence answered 4/12, 2020 at 17:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.