Skip to content

Commit

Permalink
Merge pull request #5311 from gavacho/nullable-boolean-labels
Browse files Browse the repository at this point in the history
Allow the option labels of NullableBooleanInput to be customized
  • Loading branch information
fzaninotto authored Oct 1, 2020
2 parents 2ad0138 + 4f97ed5 commit 006bd59
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 35 deletions.
30 changes: 17 additions & 13 deletions docs/Inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -450,30 +450,34 @@ import { NullableBooleanInput } from 'react-admin';

![NullableBooleanInput](./img/nullable-boolean-input.png)

`<NullableBooleanInput />` 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';

<NullableBooleanInput
label="Commentable"
source="commentable"
displayNull
/>
```

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');

<Admin i18nProvider={i18nProvider}></Admin>
```

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
label="Commentable"
source="commentable"
nullLabel="Either"
falseLabel="No"
trueLabel="Yes"
/>
```

![NullableBooleanInput](./img/nullable-boolean-input-null-label.png)

`<BooleanInput>` and `<NullableBooleanInput>` also accept the [common input props](./Inputs.md#common-input-props).
Expand Down
66 changes: 66 additions & 0 deletions packages/ra-ui-materialui/src/input/NullableBooleanInput.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,70 @@ describe('<NullableBooleanInput />', () => {
'true'
);
});

it('should allow to customize the label of the null option', () => {
const { getByRole, getByText, container } = render(
<Form
onSubmit={jest.fn}
initialValues={{
isPublished: null,
}}
render={() => (
<NullableBooleanInput
source="isPublished"
resource="posts"
nullLabel="example null label"
/>
)}
/>
);
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(
<Form
onSubmit={jest.fn}
initialValues={{
isPublished: null,
}}
render={() => (
<NullableBooleanInput
source="isPublished"
resource="posts"
falseLabel="example false label"
/>
)}
/>
);
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(
<Form
onSubmit={jest.fn}
initialValues={{
isPublished: null,
}}
render={() => (
<NullableBooleanInput
source="isPublished"
resource="posts"
trueLabel="example true label"
/>
)}
/>
);
expect(container.querySelector('input').getAttribute('value')).toBe('');
const select = getByRole('button');
fireEvent.mouseDown(select);
expect(getByText('example true label')).not.toBeNull();
});
});
40 changes: 18 additions & 22 deletions packages/ra-ui-materialui/src/input/NullableBooleanInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,14 @@ const getStringFromBoolean = (value?: boolean | null): string => {
return '';
};

const NullableBooleanInput: FunctionComponent<
InputProps<TextFieldProps> & Omit<TextFieldProps, 'label' | 'helperText'>
> = props => {
export type NullableBooleanInputProps = InputProps<TextFieldProps> &
Omit<TextFieldProps, 'label' | 'helperText'> & {
nullLabel?: string;
falseLabel?: string;
trueLabel?: string;
};

const NullableBooleanInput: FunctionComponent<NullableBooleanInputProps> = props => {
const {
className,
classes: classesOverride,
Expand All @@ -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);
Expand All @@ -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 (
<TextField
id={id}
Expand All @@ -108,12 +101,12 @@ const NullableBooleanInput: FunctionComponent<
}
className={classnames(classes.input, className)}
variant={variant}
{...enhancedOptions}
{...options}
{...sanitizeRestProps(rest)}
>
<MenuItem value="">{translate('ra.boolean.null')}</MenuItem>
<MenuItem value="false">{translate('ra.boolean.false')}</MenuItem>
<MenuItem value="true">{translate('ra.boolean.true')}</MenuItem>
<MenuItem value="">{translate(nullLabel)}</MenuItem>
<MenuItem value="false">{translate(falseLabel)}</MenuItem>
<MenuItem value="true">{translate(trueLabel)}</MenuItem>
</TextField>
);
};
Expand All @@ -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;

0 comments on commit 006bd59

Please sign in to comment.