Skip to content

Commit 860a48e

Browse files
authoredAug 22, 2022
Merge pull request #8067 from marmelab/simpleformiterator
Add support for SimpleFormIterator inline and sx props
2 parents 861f475 + 2d28f45 commit 860a48e

File tree

5 files changed

+121
-4
lines changed

5 files changed

+121
-4
lines changed
 

‎docs/ArrayInput.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,26 @@ import { ArrayInput, SimpleFormIterator, DateInput, TextInput } from 'react-admi
4242

4343
`<ArrayInput>` expects a single child, which must be a *form iterator* component. A form iterator is a component accepting a `fields` object as passed by [react-hook-form](https://react-hook-form.com/api/usefieldarray), and defining a layout for an array of fields. It also receives several functions to manipulate the array values. For instance, the `<SimpleFormIterator>` component displays an array of react-admin Inputs in an unordered list (`<ul>`), one sub-form by list item (`<li>`). It also provides controls for adding and removing a sub-record (a backlink in this example).
4444

45+
By using `<SimpleFormIterator inline>`, child inputs apper inline.
46+
47+
```jsx
48+
import { ArrayInput, SimpleFormIterator, DateInput, TextInput } from 'react-admin';
49+
50+
<ArrayInput source="backlinks">
51+
<SimpleFormIterator inline>
52+
<DateInput source="date" />
53+
<TextInput source="url" />
54+
</SimpleFormIterator>
55+
</ArrayInput>
56+
```
57+
4558
You can pass `disableAdd`, `disableRemove` and `disableReordering` as props of `SimpleFormIterator`, to disable `ADD`, `REMOVE` and the `UP/DOWN` button(s) respectively. Default value of each is `false`.
4659

4760
```jsx
4861
import { ArrayInput, SimpleFormIterator, DateInput, TextInput } from 'react-admin';
4962

5063
<ArrayInput source="backlinks">
51-
<SimpleFormIterator disableRemove >
64+
<SimpleFormIterator disableRemove>
5265
<DateInput source="date" />
5366
<TextInput source="url" />
5467
</SimpleFormIterator>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import * as React from 'react';
2+
3+
import { Edit } from '../../detail';
4+
import { SimpleForm } from '../../form';
5+
import { ArrayInput } from './ArrayInput';
6+
import { SimpleFormIterator } from './SimpleFormIterator';
7+
import { TextInput } from '../TextInput';
8+
import { AdminContext } from '../../AdminContext';
9+
10+
export default { title: 'ra-ui-materialui/input/SimpleFormIterator' };
11+
12+
const dataProvider = {
13+
getOne: () =>
14+
Promise.resolve({
15+
data: {
16+
id: 1,
17+
title: 'War and Peace',
18+
authors: [
19+
{
20+
name: 'Leo Tolstoy',
21+
role: 'head_writer',
22+
},
23+
{
24+
name: 'Alexander Pushkin',
25+
role: 'co_writer',
26+
},
27+
],
28+
},
29+
}),
30+
} as any;
31+
32+
export const Basic = () => (
33+
<AdminContext dataProvider={dataProvider}>
34+
<Edit resource="books" id="1">
35+
<SimpleForm>
36+
<ArrayInput source="authors" fullWidth>
37+
<SimpleFormIterator>
38+
<TextInput source="name" />
39+
<TextInput source="role" />
40+
</SimpleFormIterator>
41+
</ArrayInput>
42+
</SimpleForm>
43+
</Edit>
44+
</AdminContext>
45+
);
46+
47+
export const Inline = () => (
48+
<AdminContext dataProvider={dataProvider}>
49+
<Edit resource="books" id="1">
50+
<SimpleForm>
51+
<ArrayInput source="authors" fullWidth>
52+
<SimpleFormIterator inline>
53+
<TextInput source="name" />
54+
<TextInput source="role" />
55+
</SimpleFormIterator>
56+
</ArrayInput>
57+
</SimpleForm>
58+
</Edit>
59+
</AdminContext>
60+
);
61+
62+
export const Sx = () => (
63+
<AdminContext dataProvider={dataProvider}>
64+
<Edit resource="books" id="1">
65+
<SimpleForm>
66+
<ArrayInput source="authors" fullWidth>
67+
<SimpleFormIterator
68+
sx={{
69+
border: 'solid lightgrey 1px',
70+
borderRadius: 2,
71+
mt: 3,
72+
p: 1,
73+
'& .RaSimpleFormIterator-form': {
74+
flexDirection: 'row',
75+
gap: '1em',
76+
},
77+
}}
78+
>
79+
<TextInput source="name" />
80+
<TextInput source="role" />
81+
</SimpleFormIterator>
82+
</ArrayInput>
83+
</SimpleForm>
84+
</Edit>
85+
</AdminContext>
86+
);

‎packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx

+12-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
useCallback,
1010
useMemo,
1111
} from 'react';
12-
import { styled } from '@mui/material';
12+
import { styled, SxProps } from '@mui/material';
1313
import clsx from 'clsx';
1414
import get from 'lodash/get';
1515
import PropTypes from 'prop-types';
@@ -43,7 +43,9 @@ export const SimpleFormIterator = (props: SimpleFormIteratorProps) => {
4343
disableAdd,
4444
disableRemove,
4545
disableReordering,
46+
inline,
4647
getItemLabel = DefaultLabelFn,
48+
sx,
4749
} = props;
4850
const { append, fields, move, remove } = useArrayInput(props);
4951
const record = useRecordContext(props);
@@ -106,7 +108,7 @@ export const SimpleFormIterator = (props: SimpleFormIteratorProps) => {
106108
);
107109
return fields ? (
108110
<SimpleFormIteratorContext.Provider value={context}>
109-
<Root className={className}>
111+
<Root className={className} sx={sx}>
110112
{fields.map((member, index) => (
111113
<SimpleFormIteratorItem
112114
key={member.id}
@@ -124,6 +126,7 @@ export const SimpleFormIterator = (props: SimpleFormIteratorProps) => {
124126
reOrderButtons={reOrderButtons}
125127
resource={resource}
126128
source={source}
129+
inline={inline}
127130
>
128131
{children}
129132
</SimpleFormIteratorItem>
@@ -163,6 +166,7 @@ SimpleFormIterator.propTypes = {
163166
fields: PropTypes.array,
164167
fieldState: PropTypes.object,
165168
formState: PropTypes.object,
169+
inline: PropTypes.bool,
166170
record: PropTypes.object,
167171
source: PropTypes.string,
168172
resource: PropTypes.string,
@@ -182,6 +186,7 @@ export interface SimpleFormIteratorProps extends Partial<UseFieldArrayReturn> {
182186
disableRemove?: boolean | DisableRemoveFunction;
183187
disableReordering?: boolean;
184188
getItemLabel?: (index: number) => string;
189+
inline?: boolean;
185190
meta?: {
186191
// the type defined in FieldArrayRenderProps says error is boolean, which is wrong.
187192
error?: any;
@@ -192,6 +197,7 @@ export interface SimpleFormIteratorProps extends Partial<UseFieldArrayReturn> {
192197
reOrderButtons?: ReactElement;
193198
resource?: string;
194199
source?: string;
200+
sx?: SxProps;
195201
}
196202

197203
const Root = styled('ul', {
@@ -225,6 +231,10 @@ const Root = styled('ul', {
225231
flexDirection: 'column',
226232
flex: 2,
227233
},
234+
[`& .${SimpleFormIteratorClasses.inline}`]: {
235+
flexDirection: 'row',
236+
gap: '1em',
237+
},
228238
[`& .${SimpleFormIteratorClasses.action}`]: {
229239
paddingTop: '0.5em',
230240
},

‎packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export const SimpleFormIteratorItem = React.forwardRef(
3030
disableRemove,
3131
getItemLabel,
3232
index,
33+
inline = false,
3334
member,
3435
record,
3536
removeButton,
@@ -97,7 +98,12 @@ export const SimpleFormIteratorItem = React.forwardRef(
9798
})}
9899
</div>
99100
</div>
100-
<section className={SimpleFormIteratorClasses.form}>
101+
<section
102+
className={clsx(
103+
SimpleFormIteratorClasses.form,
104+
inline && SimpleFormIteratorClasses.inline
105+
)}
106+
>
101107
{Children.map(
102108
children,
103109
(input: ReactElement, index2) => {
@@ -146,6 +152,7 @@ export type SimpleFormIteratorItemProps = Partial<ArrayInputContextValue> & {
146152
disableReordering?: boolean;
147153
getItemLabel?: (index: number) => string;
148154
index: number;
155+
inline?: boolean;
149156
member: string;
150157
onRemoveField: (index: number) => void;
151158
onReorder: (origin: number, destination: number) => void;

‎packages/ra-ui-materialui/src/input/ArrayInput/useSimpleFormIteratorStyles.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export const SimpleFormIteratorPrefix = 'RaSimpleFormIterator';
33
export const SimpleFormIteratorClasses = {
44
line: `${SimpleFormIteratorPrefix}-line`,
55
index: `${SimpleFormIteratorPrefix}-index`,
6+
inline: `${SimpleFormIteratorPrefix}-inline`,
67
indexContainer: `${SimpleFormIteratorPrefix}-indexContainer`,
78
form: `${SimpleFormIteratorPrefix}-form`,
89
action: `${SimpleFormIteratorPrefix}-action`,

0 commit comments

Comments
 (0)