Following the discussion in https://github.com/marmelab/react-admin/issues/850, did someone manage to make a create / edit form into a modal?
Thanks,
Nicolas
Normally with working with arrays in react and you want to operate on an entry, then you pass in a callback the index of the element you want to work with. Create a new onClick handler that sets the index you want to edit and toggles the modal open
– Efficiently create record using React modal. We’ll set up a basic project providing context for the modal dialog with components and sample data. Then, we’ll go through the code, using two types of resources (Users and Posts), showing how to add User resources on the fly while creating new Posts.
Create a new onClick handler that sets the index you want to edit and toggles the modal open editByIndex(editIndex) { this.setState({ editIndex }); this.toggleModal("modalWithoutAnimation"); }
The form is in "add mode" when there is no user id parameter ( match.params.id ), otherwise it is in "edit mode".
My previous answer was deleted as it did not contains actual code but only links. Here's a new one with both:
Here's a tutorial showing how to do that: https://marmelab.com/blog/2018/08/27/react-admin-tutorials-custom-forms-related-records.html.
You can find the codesandbox here: https://codesandbox.io/s/ypp9ljxqlj
For example, let's say we want to create a new Post when working a new Comment. You can have a custom PostReferenceInput
which will show a button to create a new Post next to the input:
import React, { Fragment } from 'react';
import { Field } from 'redux-form';
import { ReferenceInput, SelectInput } from 'react-admin';
import PostQuickCreateButton from './PostQuickCreateButton';
const PostReferenceInput = props => (
<Fragment>
<ReferenceInput {...props}>
<SelectInput optionText="title" />
</ReferenceInput>
<PostQuickCreateButton />
</Fragment>
);
export default PostReferenceInput;
The PostQuickCreateButton
would then be responsible for showing a modal/sidepanel/whatever and handle the actual creation. Note that we use the dataProvider directly so that we know when to close the modal:
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import { change, submit, isSubmitting } from 'redux-form';
import {
fetchEnd,
fetchStart,
required,
showNotification,
crudGetMatching,
Button,
SaveButton,
SimpleForm,
TextInput,
LongTextInput,
CREATE,
REDUX_FORM_NAME
} from 'react-admin';
import IconContentAdd from '@material-ui/icons/Add';
import IconCancel from '@material-ui/icons/Cancel';
import Dialog from '@material-ui/core/Dialog';
import DialogTitle from '@material-ui/core/DialogTitle';
import DialogContent from '@material-ui/core/DialogContent';
import DialogActions from '@material-ui/core/DialogActions';
import dataProvider from '../dataProvider';
class PostQuickCreateButton extends Component {
state = {
error: false,
showDialog: false
};
handleClick = () => {
this.setState({ showDialog: true });
};
handleCloseClick = () => {
this.setState({ showDialog: false });
};
handleSaveClick = () => {
const { submit } = this.props;
// Trigger a submit of our custom quick create form
// This is needed because our modal action buttons are oustide the form
submit('post-quick-create');
};
handleSubmit = values => {
const {
change,
crudGetMatching,
fetchStart,
fetchEnd,
showNotification
} = this.props;
// Dispatch an action letting react-admin know a API call is ongoing
fetchStart();
// As we want to know when the new post has been created in order to close the modal, we use the
// dataProvider directly
dataProvider(CREATE, 'posts', { data: values })
.then(({ data }) => {
// Refresh the choices of the ReferenceInput to ensure our newly created post
// always appear, even after selecting another post
crudGetMatching(
'posts',
'comments@post_id',
{ page: 1, perPage: 25 },
{ field: 'id', order: 'DESC' },
{}
);
// Update the main react-admin form (in this case, the comments creation form)
change(REDUX_FORM_NAME, 'post_id', data.id);
this.setState({ showDialog: false });
})
.catch(error => {
showNotification(error.message, 'error');
})
.finally(() => {
// Dispatch an action letting react-admin know a API call has ended
fetchEnd();
});
};
render() {
const { showDialog } = this.state;
const { isSubmitting } = this.props;
return (
<Fragment>
<Button onClick={this.handleClick} label="ra.action.create">
<IconContentAdd />
</Button>
<Dialog
fullWidth
open={showDialog}
onClose={this.handleCloseClick}
aria-label="Create post"
>
<DialogTitle>Create post</DialogTitle>
<DialogContent>
<SimpleForm
// We override the redux-form name to avoid collision with the react-admin main form
form="post-quick-create"
resource="posts"
// We override the redux-form onSubmit prop to handle the submission ourselves
onSubmit={this.handleSubmit}
// We want no toolbar at all as we have our modal actions
toolbar={null}
>
<TextInput source="title" validate={required()} />
<LongTextInput
source="teaser"
validate={required()}
/>
</SimpleForm>
</DialogContent>
<DialogActions>
<SaveButton
saving={isSubmitting}
onClick={this.handleSaveClick}
/>
<Button
label="ra.action.cancel"
onClick={this.handleCloseClick}
>
<IconCancel />
</Button>
</DialogActions>
</Dialog>
</Fragment>
);
}
}
const mapStateToProps = state => ({
isSubmitting: isSubmitting('post-quick-create')(state)
});
const mapDispatchToProps = {
change,
crudGetMatching,
fetchEnd,
fetchStart,
showNotification,
submit
};
export default connect(mapStateToProps, mapDispatchToProps)(
PostQuickCreateButton
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With