diff --git a/docs/Inputs.md b/docs/Inputs.md index 99f2fbed991..776d516e904 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -174,7 +174,7 @@ By default the component matches choices with the current input searchText: if i If you want to limit the initial choices shown to the current value only, you can set the `limitChoicesToValue` prop. -When dealing with a large amount of `choices` you may need to limit the number of suggestions that are rendered in order to maintain usable performance. The `shouldRenderSuggestions` is an optional prop that allows you to set conditions on when to render suggestions. An easy way to improve performance would be to skip rendering until the user has entered 2 or 3 characters in the search box. This lowers the result set significantly, and might be all you need (depending on your data set). +When dealing with a large amount of `choices` you may need to limit the number of suggestions that are rendered in order to maintain usable performance. The `shouldRenderSuggestions` is an optional prop that allows you to set conditions on when to render suggestions. An easy way to improve performance would be to skip rendering until the user has entered 2 or 3 characters in the search box. This lowers the result set significantly, and might be all you need (depending on your data set). Ex. ` { return val.trim().length > 2 }} />` would not render any suggestions until the 3rd character was entered. This prop is passed to the underlying `react-autosuggest` component and is documented [here](https://github.com/moroshko/react-autosuggest#should-render-suggestions-prop). `` renders a material-ui `` component. Use the `options` attribute to override any of the `` attributes: @@ -289,7 +289,7 @@ By default the component matches choices with the current input searchText. For If you want to limit the initial choices shown to the current value only, you can set the `limitChoicesToValue` prop. -When dealing with a large amount of `choices` you may need to limit the number of suggestions that are rendered in order to maintain usable performance. The `shouldRenderSuggestions` is an optional prop that allows you to set conditions on when to render suggestions. An easy way to improve performance would be to skip rendering until the user has entered 2 or 3 characters in the search box. This lowers the result set significantly, and might be all you need (depending on your data set). +When dealing with a large amount of `choices` you may need to limit the number of suggestions that are rendered in order to maintain usable performance. The `shouldRenderSuggestions` is an optional prop that allows you to set conditions on when to render suggestions. An easy way to improve performance would be to skip rendering until the user has entered 2 or 3 characters in the search box. This lowers the result set significantly, and might be all you need (depending on your data set). Ex. ` { return val.trim().length > 2 }} />` would not render any suggestions until the 3rd character was entered. This prop is passed to the underlying `react-autosuggest` component and is documented [here](https://github.com/moroshko/react-autosuggest#should-render-suggestions-prop). Lastly, `` renders a [material-ui-chip-input](https://github.com/TeamWertarbyte/material-ui-chip-input) component. Use the `options` attribute to override any of the `` attributes: @@ -1008,8 +1008,7 @@ const FullNameField = ({ record }) => {record.first_name} {record.last_nam }/> ``` -Enabling the `allowEmpty` props adds an empty choice (with a default `null` value, which you can overwrite with the `emptyValue` prop) on top of the options, and makes the value nullable: - +Enabling the `allowEmpty` props adds an empty choice (with a default `null` value, which you can overwrite with the `emptyValue` prop) on top of the options, and makes the value nullable. You can furthermore customize the `MenuItem` for the empty choice by using the `emptyText` prop, which can receive either a string or a React Element, which doesn't receive any props. ```jsx ``` -You can use a custom field name by setting `disableValue` prop: +You can use a custom field name by setting `disableValue` prop: ```jsx const choices = [ diff --git a/packages/ra-ui-materialui/src/input/SelectInput.js b/packages/ra-ui-materialui/src/input/SelectInput.js index 75d23396986..d73ab35b814 100644 --- a/packages/ra-ui-materialui/src/input/SelectInput.js +++ b/packages/ra-ui-materialui/src/input/SelectInput.js @@ -137,6 +137,7 @@ export const SelectInput = ({ classes, className, disableValue, + emptyText, emptyValue, helperText, input, @@ -176,6 +177,15 @@ export const SelectInput = ({ [input, setValue] ); + const renderEmptyItemOption = useCallback( + emptyText => { + return React.isValidElement(emptyText) + ? React.cloneElement(emptyText) + : translate(emptyText, { _: emptyText }); + }, + [emptyText, translate] + ); + const renderMenuItemOption = useCallback( choice => { if (React.isValidElement(optionText)) { @@ -231,7 +241,11 @@ export const SelectInput = ({ {...sanitizeRestProps(rest)} onChange={handleChange} > - {allowEmpty ? : null} + {allowEmpty ? ( + + {renderEmptyItemOption(emptyText)} + + ) : null} {choices.map(choice => ( ', () => { assert.equal(options[0].getAttribute('data-value'), emptyValue); }); + it('should add an empty menu with proper text when emptyText is a string', () => { + const emptyText = 'Default'; + + const { getByRole, getByText, queryAllByRole } = render( + + ); + const EmptyMenuElement = getByRole('button'); + fireEvent.click(EmptyMenuElement); + + const options = queryAllByRole('option'); + assert.equal(options.length, 1); + + assert.ok(getByText('Default')); + }); + + it('should add an empty menu with proper text when emptyText is a React element', () => { + const emptyText = ( +
+ Empty choice +
+ ); + + const { getByRole, getByText, queryAllByRole } = render( + + ); + const EmptyMenuElement = getByRole('button'); + fireEvent.click(EmptyMenuElement); + + const options = queryAllByRole('option'); + assert.equal(options.length, 1); + + assert.ok(getByText('Empty choice')); + }); + it('should not add a falsy (null or false) element when allowEmpty is false', () => { const { getByRole, queryAllByRole } = render(