Skip to content

Commit

Permalink
Merge pull request #5940 from paulo9mv/disable-select-array-input-opt…
Browse files Browse the repository at this point in the history
…ions

feat: add disable options to SelectArrayInput
  • Loading branch information
fzaninotto committed Feb 26, 2021
2 parents c4be146 + 2d55102 commit e989299
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 2 deletions.
22 changes: 22 additions & 0 deletions docs/Inputs.md
Expand Up @@ -1338,6 +1338,28 @@ const choices = [
];
```

You can render any item as disabled by setting its `disabled` property to `true`:

```jsx
const choices = [
{ _id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
{ _id: 456, full_name: 'Jane Austen', sex: 'F' },
{ _id: 1, full_name: 'System Administrator', sex: 'F', disabled: true },
];
<SelectArrayInput source="author_id" choices={choices} optionText="full_name" optionValue="_id" />
```

You can use a custom field name by setting the `disableValue` prop:

```jsx
const choices = [
{ _id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
{ _id: 456, full_name: 'Jane Austen', sex: 'F' },
{ _id: 987, full_name: 'Jack Harden', sex: 'M', not_available: true },
];
<SelectArrayInput source="contact_id" choices={choices} optionText="full_name" optionValue="_id" disableValue="not_available" />
```

Lastly, use the `options` attribute if you want to override any of the `<Select>` attributes:

{% raw %}
Expand Down
7 changes: 7 additions & 0 deletions packages/ra-core/src/form/useChoices.ts
Expand Up @@ -29,6 +29,7 @@ export interface ChoicesProps {
export interface UseChoicesOptions {
optionValue?: string;
optionText?: OptionTextElement | OptionText | string;
disableValue?: string;
translateChoice?: boolean;
}

Expand All @@ -46,6 +47,7 @@ export interface UseChoicesOptions {
const useChoices = ({
optionText = 'name',
optionValue = 'id',
disableValue = 'disabled',
translateChoice = true,
}: UseChoicesOptions) => {
const translate = useTranslate();
Expand Down Expand Up @@ -73,9 +75,14 @@ const useChoices = ({
optionValue,
]);

const getDisableValue = useCallback(choice => get(choice, disableValue), [
disableValue,
]);

return {
getChoiceText,
getChoiceValue,
getDisableValue,
};
};

Expand Down
23 changes: 23 additions & 0 deletions packages/ra-ui-materialui/src/input/SelectArrayInput.spec.tsx
Expand Up @@ -171,6 +171,29 @@ describe('<SelectArrayInput />', () => {
expect(queryByText('Programming')).not.toBeNull();
});

it('should render disable choices marked so', () => {
const { getByRole, getByText } = render(
<Form
onSubmit={jest.fn()}
render={() => (
<SelectArrayInput
{...defaultProps}
choices={[
{ id: 'ang', name: 'Angular' },
{ id: 'rea', name: 'React', disabled: true },
]}
/>
)}
/>
);
const select = getByRole('button');
fireEvent.mouseDown(select);
const option1 = getByText('Angular');
expect(option1.getAttribute('aria-disabled')).toEqual('false');

const option2 = getByText('React');
expect(option2.getAttribute('aria-disabled')).toEqual('true');
});
it('should translate the choices', () => {
const { getByRole, queryByText } = render(
<TestTranslationProvider translate={x => `**${x}**`}>
Expand Down
10 changes: 8 additions & 2 deletions packages/ra-ui-materialui/src/input/SelectArrayInput.tsx
Expand Up @@ -41,6 +41,7 @@ const sanitizeRestProps = ({
crudGetMInputWithOptionsPropsatching,
crudGetOInputWithOptionsPropsne,
defaultValue,
disableValue,
filter,
filterToQuery,
formClassName,
Expand Down Expand Up @@ -143,6 +144,7 @@ const SelectArrayInput: FunctionComponent<SelectArrayInputProps> = props => {
choices = [],
classes: classesOverride,
className,
disableValue,
format,
helperText,
label,
Expand Down Expand Up @@ -173,9 +175,10 @@ const SelectArrayInput: FunctionComponent<SelectArrayInputProps> = props => {
}
}, []);

const { getChoiceText, getChoiceValue } = useChoices({
const { getChoiceText, getChoiceValue, getDisableValue } = useChoices({
optionText,
optionValue,
disableValue,
translateChoice,
});
const {
Expand Down Expand Up @@ -204,12 +207,13 @@ const SelectArrayInput: FunctionComponent<SelectArrayInputProps> = props => {
<MenuItem
key={getChoiceValue(choice)}
value={getChoiceValue(choice)}
disabled={getDisableValue(choice)}
>
{renderMenuItemOption(choice)}
</MenuItem>
) : null;
},
[getChoiceValue, renderMenuItemOption]
[getChoiceValue, getDisableValue, renderMenuItemOption]
);

if (loading) {
Expand Down Expand Up @@ -311,6 +315,7 @@ SelectArrayInput.propTypes = {
PropTypes.element,
]).isRequired,
optionValue: PropTypes.string.isRequired,
disableValue: PropTypes.string,
resource: PropTypes.string,
source: PropTypes.string,
translateChoice: PropTypes.bool,
Expand All @@ -320,6 +325,7 @@ SelectArrayInput.defaultProps = {
options: {},
optionText: 'name',
optionValue: 'id',
disableValue: 'disabled',
translateChoice: true,
};

Expand Down

0 comments on commit e989299

Please sign in to comment.