diff --git a/docs/Inputs.md b/docs/Inputs.md
index 4881cfaa485..4137e567248 100644
--- a/docs/Inputs.md
+++ b/docs/Inputs.md
@@ -1211,6 +1211,19 @@ import { ArrayInput, SimpleFormIterator, DateInput, TextInput } from 'react-admi
```
+Furthermore, if you want to customize the label displayed for each item, you can pass a function to `SimpleFormIterator` via the `getItemLabel` prop.
+
+```jsx
+import { ArrayInput, SimpleFormIterator, DateInput, TextInput } from 'react-admin';
+
+
+ `${index + 1}. link`}>
+
+
+
+
+```
+
**Note**: `SimpleFormIterator` only accepts `Input` components as children. If you want to use some `Fields` instead, you have to use a `` to get the correct source, as follows:
```jsx
diff --git a/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx b/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx
index 35b6a9c2009..dffb7747cb0 100644
--- a/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx
+++ b/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx
@@ -1,15 +1,14 @@
-import { fireEvent, waitFor, getByText } from '@testing-library/react';
-import * as React from 'react';
+import { ThemeProvider } from '@material-ui/core';
+import { createMuiTheme } from '@material-ui/core/styles';
+import { fireEvent, getByText, waitFor } from '@testing-library/react';
import expect from 'expect';
import { SaveContextProvider, SideEffectContextProvider } from 'ra-core';
import { renderWithRedux } from 'ra-test';
-import { ThemeProvider } from '@material-ui/core';
-import { createMuiTheme } from '@material-ui/core/styles';
-
-import SimpleFormIterator from './SimpleFormIterator';
-import TextInput from '../input/TextInput';
+import * as React from 'react';
import { ArrayInput } from '../input';
+import TextInput from '../input/TextInput';
import SimpleForm from './SimpleForm';
+import SimpleFormIterator from './SimpleFormIterator';
const theme = createMuiTheme();
@@ -499,6 +498,34 @@ describe('', () => {
expect(getByText('Custom Remove Button')).not.toBeNull();
});
+ it('should display custom row label', () => {
+ const { getByText } = renderWithRedux(
+
+
+
+
+
+ `3.${index}`}
+ >
+
+
+
+
+
+
+
+ );
+
+ expect(getByText('3.0')).toBeDefined();
+ expect(getByText('3.1')).toBeDefined();
+ });
+
it('should call the onClick method when the custom add button is clicked', async () => {
const onClick = jest.fn();
const { getByText } = renderWithRedux(
diff --git a/packages/ra-ui-materialui/src/form/SimpleFormIterator.tsx b/packages/ra-ui-materialui/src/form/SimpleFormIterator.tsx
index 1cce3872a7b..f6f9a8a5051 100644
--- a/packages/ra-ui-materialui/src/form/SimpleFormIterator.tsx
+++ b/packages/ra-ui-materialui/src/form/SimpleFormIterator.tsx
@@ -1,27 +1,26 @@
+import Button from '@material-ui/core/Button';
+import FormHelperText from '@material-ui/core/FormHelperText';
+import { makeStyles } from '@material-ui/core/styles';
+import Typography from '@material-ui/core/Typography';
+import AddIcon from '@material-ui/icons/AddCircleOutline';
+import CloseIcon from '@material-ui/icons/RemoveCircleOutline';
+import classNames from 'classnames';
+import get from 'lodash/get';
+import PropTypes from 'prop-types';
+import { Record, useTranslate, ValidationError } from 'ra-core';
import * as React from 'react';
import {
Children,
cloneElement,
+ FC,
isValidElement,
- useRef,
ReactElement,
- FC,
+ useRef,
} from 'react';
-import PropTypes from 'prop-types';
-import { CSSTransition, TransitionGroup } from 'react-transition-group';
-import get from 'lodash/get';
-import Typography from '@material-ui/core/Typography';
-import Button from '@material-ui/core/Button';
-import FormHelperText from '@material-ui/core/FormHelperText';
-import { makeStyles } from '@material-ui/core/styles';
-import CloseIcon from '@material-ui/icons/RemoveCircleOutline';
-import AddIcon from '@material-ui/icons/AddCircleOutline';
-import { useTranslate, ValidationError, Record } from 'ra-core';
-import classNames from 'classnames';
import { FieldArrayRenderProps } from 'react-final-form-arrays';
-
-import FormInput from './FormInput';
+import { CSSTransition, TransitionGroup } from 'react-transition-group';
import { ClassesOverride } from '../types';
+import FormInput from './FormInput';
const useStyles = makeStyles(
theme => ({
@@ -83,6 +82,8 @@ const DefaultAddButton = props => {
);
};
+const DefaultLabelFn = index => index + 1;
+
const DefaultRemoveButton = props => {
const classes = useStyles(props);
const translate = useTranslate();
@@ -113,6 +114,7 @@ const SimpleFormIterator: FC = props => {
margin,
TransitionProps,
defaultValue,
+ getItemLabel = DefaultLabelFn,
} = props;
const classes = useStyles(props);
const nodeRef = useRef(null);
@@ -197,7 +199,7 @@ const SimpleFormIterator: FC = props => {
variant="body1"
className={classes.index}
>
- {index + 1}
+ {getItemLabel(index)}
{Children.map(
@@ -326,6 +328,7 @@ export interface SimpleFormIteratorProps
disabled?: boolean;
disableAdd?: boolean;
disableRemove?: boolean | DisableRemoveFunction;
+ getItemLabel?: (index: number) => string;
margin?: 'none' | 'normal' | 'dense';
meta?: {
// the type defined in FieldArrayRenderProps says error is boolean, which is wrong.