diff --git a/docs/Inputs.md b/docs/Inputs.md index f9e6f28570e..6829c6d2bab 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -450,30 +450,34 @@ import { NullableBooleanInput } from 'react-admin'; ![NullableBooleanInput](./img/nullable-boolean-input.png) -`` doesn't display the empty option by default. If you want to customize its label and display it, you can use the `displayNull` prop. - -```jsx -import { NullableBooleanInput } from 'react-admin'; - - -``` - -Also you need to provide your own label for null value. +The labels of the options can be customized for the entire application by overriding the translation. ```jsx import polyglotI18nProvider from 'ra-i18n-polyglot'; import englishMessages from 'ra-language-english'; englishMessages.ra.boolean.null = 'Null label'; +englishMessages.ra.boolean.false = 'False label'; +englishMessages.ra.boolean.true = 'True label'; const i18nProvider = polyglotI18nProvider(() => englishMessages, 'en'); ``` +Additionally, individual instances of `NullableBooleanInput` may be customized by setting the `nullLabel`, `falseLabel` and `trueLabel` properties. Values specified for those properties will be translated by react-admin. + +```jsx +import { NullableBooleanInput } from 'react-admin'; + + +``` + ![NullableBooleanInput](./img/nullable-boolean-input-null-label.png) `` and `` also accept the [common input props](./Inputs.md#common-input-props). diff --git a/packages/ra-ui-materialui/src/input/NullableBooleanInput.spec.tsx b/packages/ra-ui-materialui/src/input/NullableBooleanInput.spec.tsx index c9f46d7ce4c..736b98ffde7 100644 --- a/packages/ra-ui-materialui/src/input/NullableBooleanInput.spec.tsx +++ b/packages/ra-ui-materialui/src/input/NullableBooleanInput.spec.tsx @@ -138,4 +138,70 @@ describe('', () => { 'true' ); }); + + it('should allow to customize the label of the null option', () => { + const { getByRole, getByText, container } = render( +
( + + )} + /> + ); + expect(container.querySelector('input').getAttribute('value')).toBe(''); + const select = getByRole('button'); + fireEvent.mouseDown(select); + expect(getByText('example null label')).not.toBeNull(); + }); + + it('should allow to customize the label of the false option', () => { + const { getByRole, getByText, container } = render( + ( + + )} + /> + ); + expect(container.querySelector('input').getAttribute('value')).toBe(''); + const select = getByRole('button'); + fireEvent.mouseDown(select); + expect(getByText('example false label')).not.toBeNull(); + }); + + it('should allow to customize the label of the true option', () => { + const { getByRole, getByText, container } = render( + ( + + )} + /> + ); + expect(container.querySelector('input').getAttribute('value')).toBe(''); + const select = getByRole('button'); + fireEvent.mouseDown(select); + expect(getByText('example true label')).not.toBeNull(); + }); }); diff --git a/packages/ra-ui-materialui/src/input/NullableBooleanInput.tsx b/packages/ra-ui-materialui/src/input/NullableBooleanInput.tsx index 4ba630ec778..318b4ae6be7 100644 --- a/packages/ra-ui-materialui/src/input/NullableBooleanInput.tsx +++ b/packages/ra-ui-materialui/src/input/NullableBooleanInput.tsx @@ -29,9 +29,14 @@ const getStringFromBoolean = (value?: boolean | null): string => { return ''; }; -const NullableBooleanInput: FunctionComponent< - InputProps & Omit -> = props => { +export type NullableBooleanInputProps = InputProps & + Omit & { + nullLabel?: string; + falseLabel?: string; + trueLabel?: string; + }; + +const NullableBooleanInput: FunctionComponent = props => { const { className, classes: classesOverride, @@ -43,12 +48,14 @@ const NullableBooleanInput: FunctionComponent< onChange, onFocus, options, - displayNull, parse = getBooleanFromString, resource, source, validate, variant = 'filled', + nullLabel = 'ra.boolean.null', + falseLabel = 'ra.boolean.false', + trueLabel = 'ra.boolean.true', ...rest } = props; const classes = useStyles(props); @@ -70,20 +77,6 @@ const NullableBooleanInput: FunctionComponent< validate, }); - const enhancedOptions = displayNull - ? { - ...options, - SelectProps: { - displayEmpty: true, - ...(options && options.SelectProps), - }, - InputLabelProps: { - shrink: true, - ...(options && options.InputLabelProps), - }, - } - : options; - return ( - {translate('ra.boolean.null')} - {translate('ra.boolean.false')} - {translate('ra.boolean.true')} + {translate(nullLabel)} + {translate(falseLabel)} + {translate(trueLabel)} ); }; @@ -123,6 +116,9 @@ NullableBooleanInput.propTypes = { options: PropTypes.object, resource: PropTypes.string, source: PropTypes.string, + nullLabel: PropTypes.string, + falseLabel: PropTypes.string, + trueLabel: PropTypes.string, }; export default NullableBooleanInput;