diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx index fa8b1815e64..9eb0f7bfbb3 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.tsx @@ -158,6 +158,7 @@ export const SimpleFormIterator = (props: SimpleFormIteratorProps) => { resource={resource} source={source} variant={variant} + ref={nodeRef} > {children} </SimpleFormIteratorItem> diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx index 1112fb9ee3c..0b8280e5244 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIteratorItem.tsx @@ -23,129 +23,140 @@ import { SimpleFormIteratorItemContextValue, } from './SimpleFormIteratorItemContext'; -export const SimpleFormIteratorItem = (props: SimpleFormIteratorItemProps) => { - const { - basePath, - children, - classes, - disabled, - disableReordering, - disableRemove, - getItemLabel, - index, - margin, - member, - record, - removeButton, - reOrderButtons, - resource, - source, - variant, - } = props; +export const SimpleFormIteratorItem = React.forwardRef( + (props: SimpleFormIteratorItemProps, ref: any) => { + const { + basePath, + children, + classes, + disabled, + disableReordering, + disableRemove, + getItemLabel, + index, + margin, + member, + record, + removeButton, + reOrderButtons, + resource, + source, + variant, + } = props; - const { total, reOrder, remove } = useSimpleFormIterator(); - // Returns a boolean to indicate whether to disable the remove button for certain fields. - // If disableRemove is a function, then call the function with the current record to - // determining if the button should be disabled. Otherwise, use a boolean property that - // enables or disables the button for all of the fields. - const disableRemoveField = (record: Record) => { - if (typeof disableRemove === 'boolean') { - return disableRemove; - } - return disableRemove && disableRemove(record); - }; + const { total, reOrder, remove } = useSimpleFormIterator(); + // Returns a boolean to indicate whether to disable the remove button for certain fields. + // If disableRemove is a function, then call the function with the current record to + // determining if the button should be disabled. Otherwise, use a boolean property that + // enables or disables the button for all of the fields. + const disableRemoveField = (record: Record) => { + if (typeof disableRemove === 'boolean') { + return disableRemove; + } + return disableRemove && disableRemove(record); + }; - // remove field and call the onClick event of the button passed as removeButton prop - const handleRemoveButtonClick = ( - originalOnClickHandler: MouseEventHandler, - index: number - ) => (event: MouseEvent) => { - remove(index); - if (originalOnClickHandler) { - originalOnClickHandler(event); - } - }; + // remove field and call the onClick event of the button passed as removeButton prop + const handleRemoveButtonClick = ( + originalOnClickHandler: MouseEventHandler, + index: number + ) => (event: MouseEvent) => { + remove(index); + if (originalOnClickHandler) { + originalOnClickHandler(event); + } + }; - const context = useMemo<SimpleFormIteratorItemContextValue>( - () => ({ - index, - total, - reOrder: newIndex => reOrder(index, newIndex), - remove: () => remove(index), - }), - [index, total, reOrder, remove] - ); + const context = useMemo<SimpleFormIteratorItemContextValue>( + () => ({ + index, + total, + reOrder: newIndex => reOrder(index, newIndex), + remove: () => remove(index), + }), + [index, total, reOrder, remove] + ); - return ( - <SimpleFormIteratorItemContext.Provider value={context}> - <li className={classes.line}> - <div> - <div className={classes.indexContainer}> - <Typography variant="body1" className={classes.index}> - {getItemLabel(index)} - </Typography> - {!disabled && - !disableReordering && - cloneElement(reOrderButtons, { - index, - max: total, - reOrder, + return ( + <SimpleFormIteratorItemContext.Provider value={context}> + <li className={classes.line} ref={ref}> + <div> + <div className={classes.indexContainer}> + <Typography + variant="body1" + className={classes.index} + > + {getItemLabel(index)} + </Typography> + {!disabled && + !disableReordering && + cloneElement(reOrderButtons, { + index, + max: total, + reOrder, + className: classNames( + 'button-reorder', + `button-reorder-${source}-${index}` + ), + })} + </div> + </div> + <section className={classes.form}> + {Children.map( + children, + (input: ReactElement, index2) => { + if (!isValidElement<any>(input)) { + return null; + } + const { source, ...inputProps } = input.props; + return ( + <FormInput + basePath={ + input.props.basePath || basePath + } + input={cloneElement(input, { + source: source + ? `${member}.${source}` + : member, + index: source ? undefined : index2, + label: + typeof input.props.label === + 'undefined' + ? source + ? `resources.${resource}.fields.${source}` + : undefined + : input.props.label, + disabled, + ...inputProps, + })} + record={record} + resource={resource} + variant={variant} + margin={margin} + /> + ); + } + )} + </section> + {!disabled && !disableRemoveField(record) && ( + <span className={classes.action}> + {cloneElement(removeButton, { + onClick: handleRemoveButtonClick( + removeButton.props.onClick, + index + ), className: classNames( - 'button-reorder', - `button-reorder-${source}-${index}` + 'button-remove', + `button-remove-${source}-${index}` ), })} - </div> - </div> - <section className={classes.form}> - {Children.map(children, (input: ReactElement, index2) => { - if (!isValidElement<any>(input)) { - return null; - } - const { source, ...inputProps } = input.props; - return ( - <FormInput - basePath={input.props.basePath || basePath} - input={cloneElement(input, { - source: source - ? `${member}.${source}` - : member, - index: source ? undefined : index2, - label: - typeof input.props.label === 'undefined' - ? source - ? `resources.${resource}.fields.${source}` - : undefined - : input.props.label, - disabled, - ...inputProps, - })} - record={record} - resource={resource} - variant={variant} - margin={margin} - /> - ); - })} - </section> - {!disabled && !disableRemoveField(record) && ( - <span className={classes.action}> - {cloneElement(removeButton, { - onClick: handleRemoveButtonClick( - removeButton.props.onClick, - index - ), - className: classNames( - 'button-remove', - `button-remove-${source}-${index}` - ), - })} - </span> - )} - </li> - </SimpleFormIteratorItemContext.Provider> - ); -}; + </span> + )} + </li> + </SimpleFormIteratorItemContext.Provider> + ); + } +); export type DisableRemoveFunction = (record: Record) => boolean;