--- layout: default title: "The Create and Edit Views" --- # The Create and Edit Views The Create and Edit views both display a form, initialized with an empty record (for the Create view) or with a record fetched from the API (for the Edit view). The `` and `` components then delegate the actual rendering of the form to a form component - usually ``. This form component uses its children ([``](./Inputs.md) components) to render each form input. ![post creation form](./img/create-view.png) ![post edition form](./img/edit-view.png) ## The `` and `` components The `` and `` components render the page title and actions, and fetch the record from the data provider. They are not responsible for rendering the actual form - that's the job of their child component (usually ``), to which they pass the `record` as prop. Here are all the props accepted by the `` and `` components: * [`title`](#page-title) * [`actions`](#actions) * [`aside`](#aside-component) * [`successMessage`](#success-message) * [`undoable`](#undoable) (`` only) Here is the minimal code necessary to display a form to create and edit comments: {% raw %} ```jsx // in src/App.js import React from 'react'; import { Admin, Resource } from 'react-admin'; import jsonServerProvider from 'ra-data-json-server'; import { PostCreate, PostEdit } from './posts'; const App = () => ( ); export default App; // in src/posts.js import React from 'react'; import { Create, Edit, SimpleForm, TextInput, DateInput, ReferenceManyField, Datagrid, TextField, DateField, EditButton } from 'react-admin'; import RichTextInput from 'ra-input-rich-text'; export const PostCreate = (props) => ( ); export const PostEdit = (props) => ( ); ``` {% endraw %} That's enough to display the post edit form: ![post edition form](./img/post-edition.png) **Tip**: You might find it cumbersome to repeat the same input components for both the `` and the `` view. In practice, these two views almost never have exactly the same form inputs. For instance, in the previous snippet, the `` views shows related comments to the current post, which makes no sense for a new post. Having two separate sets of input components for the two views is therefore a deliberate choice. However, if you have the same set of input components, export them as a custom Form component to avoid repetition. `` accepts a `record` prop, to initialize the form based on an value object. ### Page Title By default, the title for the Create view is "Create [resource_name]", and the title for the Edit view is "Edit [resource_name] #[record_id]". You can customize this title by specifying a custom `title` prop: ```jsx export const PostEdit = (props) => ( ... ); ``` More interestingly, you can pass an element as `title`. React-admin clones this element and, in the ``, injects the current `record`. This allows to customize the title according to the current record: ```jsx const PostTitle = ({ record }) => { return Post {record ? `"${record.title}"` : ''}; }; export const PostEdit = (props) => ( } {...props}> ... ); ``` ### Actions You can replace the list of default actions by your own element using the `actions` prop: ```jsx import React from 'react'; import Button from '@material-ui/core/Button'; import { TopToolbar, ShowButton } from 'react-admin'; const PostEditActions = ({ basePath, data, resource }) => ( {/* Add your custom actions */} ); export const PostEdit = (props) => ( } {...props}> ... ); ``` ### Aside component You may want to display additional information on the side of the form. Use the `aside` prop for that, passing the component of your choice: {% raw %} ```jsx const Aside = () => (
Post details Posts will only be published one an editor approves them
); const PostEdit = props => ( } {...props}> ... ``` {% endraw %} The `aside` component receives the same props as the `Edit` or `Create` child component: `basePath`, `record`, `resource`, and `version`. That means you can display non-editable details of the current record in the aside component: {% raw %} ```jsx const Aside = ({ record }) => (
Post details {record && ( Creation date: {record.createdAt} )}
); ``` {% endraw %} **Tip**: Always test that the `record` is defined before using it, as react-admin starts rendering the UI before the API call is over. ### Success message Once the `dataProvider` returns successfully after save, users see a generic notification ("Element created" / "Element updated"). You can customize this message by passing a `successMessage` prop: ```jsx const PostEdit = props => ( ... ``` **Tip**: The message will be translated. ### Undoable By default, the Save and Delete actions are undoable, i.e. react-admin only sends the related request to the data provider after a short delay, during which the user can cancel the action. This is part of the "optimistic rendering" strategy of react-admin ; it makes the user interactions more reactive. You can disable this behavior by setting `undoable={false}`. With that setting, clicking on the Delete button displays a confirmation dialog. Both the Save and the Delete actions become blocking, and delay the refresh of the screen until the data provider responds. ```jsx const PostEdit = props => ( ... ``` **Tip**: If you want a confirmation dialog for the Delete button but don't mind undoable Edits, then pass a [custom toolbar](#toolbar) to the form, as follows: ```jsx import React from 'react'; import { Toolbar, SaveButton, DeleteButton, Edit, SimpleForm, } from 'react-admin'; import { makeStyles } from '@material-ui/core/styles'; const useStyles = makeStyles({ toolbar: { display: 'flex', justifyContent: 'space-between', }, }); const CustomToolbar = props => ( ); const PostEdit = props => ( }> ... ); ``` ## Prefilling a `` Record You may need to prepopulate a record based on another one. For that use case, use the `` component. It expects a `record` and a `basePath` (usually injected to children of ``, ``, ``, etc.), so it's as simple to use as a regular field or input. For instance, to allow cloning all the posts from the list: ```jsx import React from 'react'; import { List, Datagrid, TextField, CloneButton } from 'react-admin'; const PostList = props => ( ); ``` Alternately, you may need to prepopulate a record based on a *related* record. For instance, in a `PostList` component, you may want to display a button to create a comment related to the current post. Clicking on that button would lead to a `CommentCreate` page where the `post_id` is preset to the id of the Post. **Note** `` is designed to be used in an edit view `` component, not inside a ``. The `Toolbar` is basically for submitting the form, not for going to another resource. By default, the `` view starts with an empty `record`. However, if the `location` object (injected by [react-router-dom](https://reacttraining.com/react-router/web/api/location)) contains a `record` in its `state`, the `` view uses that `record` instead of the empty object. That's how the `` works behind the hood. That means that if you want to create a link to a creation form, presetting *some* values, all you have to do is to set the location `state`. `react-router-dom` provides the `` component for that: {% raw %} ```jsx import React from 'react'; import { Datagrid } from 'react-admin'; import Button from '@material-ui/core/Button'; import { Link } from 'react-router-dom'; const CreateRelatedCommentButton = ({ record }) => ( ); export default PostList = props => ( ... ) ``` {% endraw %} **Tip**: To style the button with the main color from the material-ui theme, use the `Link` component from the `react-admin` package rather than the one from `react-router-dom`. **Tip**: The `` component also watches the `location.search` (the query string in the URL) in addition to `location.state` (a cross-page message hidden in the router memory). So the `CreateRelatedCommentButton` could, in theory, be written as: {% raw %} ```jsx import React from 'react'; import Button from '@material-ui/core/Button'; import { Link } from 'react-router-dom'; const CreateRelatedCommentButton = ({ record }) => (