Skip to content

Commit 2d88ccf

Browse files
authored
Merge pull request #10696 from marmelab/rewrite-autocompleteinput-create-examples
[Doc] improve AutocompleteInput create example
2 parents b737dd1 + 7ee0796 commit 2d88ccf

File tree

2 files changed

+130
-136
lines changed

2 files changed

+130
-136
lines changed

docs/AutocompleteInput.md

Lines changed: 80 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ The form value for the source must be the selected value, e.g.
5151

5252
**Tip**: If you need to let users select more than one item in the list, check out the [`<AutocompleteArrayInput>`](./AutocompleteArrayInput.md) component.
5353

54-
**Tip**: `<AutocompleteInput>` is a stateless component, so it only allows to *filter* the list of choices, not to *extend* it. If you need to populate the list of choices based on the result from a `fetch` call (and if [`<ReferenceInput>`](./ReferenceInput.md) doesn't cover your need), you'll have to [write your own Input component](./Inputs.md#writing-your-own-input-component) based on Material UI `<Autocomplete>` component.
55-
5654
## Props
5755

5856
| Prop | Required | Type | Default | Description |
@@ -153,65 +151,70 @@ To allow users to add new options, pass a React element as the `create` prop. `<
153151

154152
{% raw %}
155153
```jsx
156-
import { CreateCategory } from './CreateCategory';
154+
import { CreateAuthor } from './CreateAuthor';
157155

158-
const PostCreate = () => (
156+
const BookCreate = () => (
159157
<Create>
160158
<SimpleForm>
161-
<TextInput source="title" />
162-
<ReferenceInput source="category_id" reference="categories">
163-
<AutocompleteInput create={<CreateCategory />} />
159+
<ReferenceInput reference="authors" source="author">
160+
<AutocompleteInput
161+
create={<CreateAuthor />}
162+
/>
164163
</ReferenceInput>
165164
</SimpleForm>
166165
</Create>
167166
);
168167

169-
// in ./CreateCategory.js
168+
// in ./CreateAuthor.js
170169
import React from 'react';
171-
import { useCreate, useCreateSuggestionContext } from 'react-admin';
170+
import { CreateBase, SimpleForm, TextInput, useCreateSuggestionContext } from 'react-admin';
171+
import CloseIcon from '@mui/icons-material/Close';
172172
import {
173173
Button,
174174
Dialog,
175-
DialogActions,
176175
DialogContent,
177-
TextField,
176+
DialogTitle,
177+
IconButton,
178178
} from '@mui/material';
179179

180-
const CreateCategory = () => {
180+
const CreateAuthor = () => {
181181
const { filter, onCancel, onCreate } = useCreateSuggestionContext();
182-
const [create] = useCreate();
183-
const [value, setValue] = React.useState(filter || '');
184-
185-
const handleSubmit = event => {
186-
event.preventDefault();
187-
create(
188-
'categories',
189-
{ data: { title: value } },
190-
{
191-
onSuccess: (data) => {
192-
setValue('');
193-
onCreate(data);
194-
},
195-
}
196-
);
182+
183+
const onAuthorCreate = author => {
184+
onCreate(author);
197185
};
198186

199187
return (
200188
<Dialog open onClose={onCancel}>
201-
<form onSubmit={handleSubmit}>
202-
<DialogContent>
203-
<TextField
204-
label="New category name"
205-
value={value}
206-
onChange={event => setValue(event.target.value)}
207-
autoFocus
208-
/>
209-
</DialogContent>
210-
<DialogActions>
211-
<Button type="submit">Save</Button>
212-
<Button onClick={onCancel}>Cancel</Button>
213-
</DialogActions>
214-
</form>
189+
<DialogTitle sx={{ m: 0, p: 2 }}>Create Author</DialogTitle>
190+
<IconButton
191+
aria-label="close"
192+
onClick={onCancel}
193+
sx={theme => ({
194+
position: 'absolute',
195+
right: 8,
196+
top: 8,
197+
color: theme.palette.grey[500],
198+
})}
199+
>
200+
<CloseIcon />
201+
</IconButton>
202+
<DialogContent sx={{ p: 0 }}>
203+
<CreateBase
204+
redirect={false}
205+
resource="authors"
206+
mutationOptions={{
207+
onSuccess: author => {
208+
onAuthorCreate(author);
209+
},
210+
}}
211+
>
212+
<SimpleForm defaultValues={{ name: filter }}>
213+
<TextInput source="name" helperText={false} />
214+
<TextInput source="language" helperText={false} autoFocus />
215+
</SimpleForm>
216+
</CreateBase>
217+
</DialogContent>
215218
</Dialog>
216219
);
217220
};
@@ -871,21 +874,22 @@ Use the `create` prop when you want a more polished or complex UI. For example a
871874
import {
872875
AutocompleteInput,
873876
Create,
877+
CreateBase,
874878
ReferenceInput,
875879
SimpleForm,
876880
TextInput,
877881
useCreate,
878-
useCreateSuggestionContext
882+
useCreateSuggestionContext,
879883
} from 'react-admin';
880884

885+
import CloseIcon from '@mui/icons-material/Close';
881886
import {
882887
Box,
883888
BoxProps,
884889
Button,
885890
Dialog,
886-
DialogActions,
887891
DialogContent,
888-
TextField,
892+
IconButton,
889893
} from '@mui/material';
890894

891895
const PostCreate = () => {
@@ -903,43 +907,42 @@ const PostCreate = () => {
903907

904908
const CreateCategory = () => {
905909
const { filter, onCancel, onCreate } = useCreateSuggestionContext();
906-
const [value, setValue] = React.useState(filter || '');
907-
const [create] = useCreate();
908-
909-
const handleSubmit = event => {
910-
event.preventDefault();
911-
create(
912-
'categories',
913-
{
914-
data: {
915-
title: value,
916-
},
917-
},
918-
{
919-
onSuccess: (data) => {
920-
setValue('');
921-
onCreate(data);
922-
},
923-
}
924-
);
910+
911+
const onCategoryCreate = category => {
912+
onCreate(category);
925913
};
926914

915+
927916
return (
928917
<Dialog open onClose={onCancel}>
929-
<form onSubmit={handleSubmit}>
930-
<DialogContent>
931-
<TextField
932-
label="New category name"
933-
value={value}
934-
onChange={event => setValue(event.target.value)}
935-
autoFocus
936-
/>
937-
</DialogContent>
938-
<DialogActions>
939-
<Button type="submit">Save</Button>
940-
<Button onClick={onCancel}>Cancel</Button>
941-
</DialogActions>
942-
</form>
918+
<DialogTitle sx={{ m: 0, p: 2 }}>Create Category</DialogTitle>
919+
<IconButton
920+
aria-label="close"
921+
onClick={onCancel}
922+
sx={theme => ({
923+
position: 'absolute',
924+
right: 8,
925+
top: 8,
926+
color: theme.palette.grey[500],
927+
})}
928+
>
929+
<CloseIcon />
930+
</IconButton>
931+
<DialogContent sx={{ p: 0 }}>
932+
<CreateBase
933+
redirect={false}
934+
resource="categories"
935+
mutationOptions={{
936+
onSuccess: category => {
937+
onCategoryCreate(category);
938+
},
939+
}}
940+
>
941+
<SimpleForm defaultValues={{ title: filter }}>
942+
<TextInput source="name" helperText={false} autoFocus/>
943+
</SimpleForm>
944+
</CreateBase>
945+
</DialogContent>
943946
</Dialog>
944947
);
945948
};

packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx

Lines changed: 50 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,45 @@ import * as React from 'react';
22
import { Admin, AdminContext } from 'react-admin';
33

44
import {
5+
CreateBase,
6+
ListBase,
7+
RecordContextProvider,
58
Resource,
9+
TestMemoryRouter,
610
required,
711
useCreate,
8-
useRecordContext,
9-
ListBase,
1012
useListContext,
11-
RecordContextProvider,
12-
TestMemoryRouter,
13+
useRecordContext,
1314
} from 'ra-core';
1415

16+
import AttributionIcon from '@mui/icons-material/Attribution';
17+
import CloseIcon from '@mui/icons-material/Close';
18+
import ExpandCircleDownIcon from '@mui/icons-material/ExpandCircleDown';
1519
import {
20+
Box,
21+
Button,
1622
Dialog,
17-
DialogContent,
1823
DialogActions,
19-
Button,
24+
DialogContent,
25+
DialogTitle,
26+
IconButton,
27+
InputAdornment,
2028
Stack,
2129
TextField,
2230
Typography,
23-
Box,
24-
InputAdornment,
2531
} from '@mui/material';
26-
import { useFormContext } from 'react-hook-form';
2732
import fakeRestProvider from 'ra-data-fakerest';
2833
import polyglotI18nProvider from 'ra-i18n-polyglot';
2934
import englishMessages from 'ra-language-english';
30-
import ExpandCircleDownIcon from '@mui/icons-material/ExpandCircleDown';
31-
import AttributionIcon from '@mui/icons-material/Attribution';
35+
import { useFormContext } from 'react-hook-form';
3236

37+
import { useState } from 'react';
3338
import { Create, Edit } from '../detail';
3439
import { SimpleForm } from '../form';
3540
import { AutocompleteInput, AutocompleteInputProps } from './AutocompleteInput';
3641
import { ReferenceInput } from './ReferenceInput';
3742
import { TextInput } from './TextInput';
3843
import { useCreateSuggestionContext } from './useSupportCreateSuggestion';
39-
import { useState } from 'react';
4044

4145
export default { title: 'ra-ui-materialui/input/AutocompleteInput' };
4246

@@ -826,56 +830,46 @@ export const InsideReferenceInputWithError = () => (
826830

827831
const CreateAuthor = () => {
828832
const { filter, onCancel, onCreate } = useCreateSuggestionContext();
829-
const [name, setName] = React.useState(filter || '');
830-
const [language, setLanguage] = React.useState('');
831-
const [create] = useCreate();
832833

833-
const handleSubmit = event => {
834-
event.preventDefault();
835-
create(
836-
'authors',
837-
{
838-
data: {
839-
name,
840-
language,
841-
},
842-
},
843-
{
844-
onSuccess: data => {
845-
setName('');
846-
setLanguage('');
847-
onCreate(data);
848-
},
849-
}
850-
);
834+
const onAuthorCreate = author => {
835+
onCreate(author);
851836
};
852837

853838
return (
854839
<Dialog open onClose={onCancel}>
855-
<form onSubmit={handleSubmit}>
856-
<DialogContent>
857-
<Stack gap={4}>
858-
<TextField
859-
name="name"
860-
label="The author name"
861-
value={name}
862-
onChange={event => setName(event.target.value)}
863-
autoFocus
864-
/>
865-
<TextField
866-
name="language"
867-
label="The author language"
868-
value={language}
869-
onChange={event => setLanguage(event.target.value)}
840+
<DialogTitle sx={{ m: 0, p: 2 }}>Create Author</DialogTitle>
841+
<IconButton
842+
aria-label="close"
843+
onClick={onCancel}
844+
sx={theme => ({
845+
position: 'absolute',
846+
right: 8,
847+
top: 8,
848+
color: theme.palette.grey[500],
849+
})}
850+
>
851+
<CloseIcon />
852+
</IconButton>
853+
<DialogContent sx={{ p: 0 }}>
854+
<CreateBase
855+
redirect={false}
856+
resource="authors"
857+
mutationOptions={{
858+
onSuccess: author => {
859+
onAuthorCreate(author);
860+
},
861+
}}
862+
>
863+
<SimpleForm defaultValues={{ name: filter }}>
864+
<TextInput source="name" helperText={false} />
865+
<TextInput
866+
source="language"
867+
helperText={false}
870868
autoFocus
871869
/>
872-
</Stack>
873-
</DialogContent>
874-
<DialogActions>
875-
<Button type="submit">Save</Button>
876-
<Button onClick={onCancel}>Cancel</Button>
877-
</DialogActions>
878-
</form>
870+
</SimpleForm>
871+
</CreateBase>
872+
</DialogContent>
879873
</Dialog>
880874
);
881875
};
@@ -891,10 +885,7 @@ const BookEditWithReferenceAndCreationSupport = () => (
891885
>
892886
<SimpleForm>
893887
<ReferenceInput reference="authors" source="author">
894-
<AutocompleteInput
895-
create={<CreateAuthor />}
896-
optionText="name"
897-
/>
888+
<AutocompleteInput create={<CreateAuthor />} />
898889
</ReferenceInput>
899890
</SimpleForm>
900891
</Edit>

0 commit comments

Comments
 (0)