Skip to content

Commit a7c1544

Browse files
committed
Add disableValue prop to CheckboxGroupInput
1 parent 2882c01 commit a7c1544

File tree

5 files changed

+139
-2
lines changed

5 files changed

+139
-2
lines changed

docs/CheckboxGroupInput.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ The form value for the source must be an array of the selected values, e.g.
6565
| `optionValue` | Optional | `string` | `id` | Field name of record containing the value to use as input value |
6666
| `row` | Optional | `boolean` | `true` | Display group of elements in a compact row. |
6767
| `translateChoice` | Optional | `boolean` | `true` | Whether the choices should be translated |
68+
| `disableValue` | Optional | `string` | `disabled` | The custom field name used in `choices` to disable some choices |
6869

6970
`<CheckboxGroupInput>` also accepts the [common input props](./Inputs.md#common-input-props).
7071

@@ -92,6 +93,17 @@ You can also use an array of objects with different properties for the label and
9293
]} optionValue="_id" optionText="label" />
9394
```
9495

96+
You can render some options as disabled by setting the `disabled` field in some choices:
97+
98+
```jsx
99+
const choices = [
100+
{ id: 'tech', name: 'Tech' },
101+
{ id: 'lifestyle', name: 'Lifestyle' },
102+
{ id: 'people', name: 'People', disabled: true },
103+
];
104+
<RadioButtonGroupInput source="category" choices={choices} />
105+
```
106+
95107
The choices are translated by default, so you can use translation identifiers as choices:
96108

97109
```jsx
@@ -255,6 +267,30 @@ However, in some cases (e.g. inside a `<ReferenceArrayInput>`), you may not want
255267
<CheckboxGroupInput source="roles" choices={choices} translateChoice={false}/>
256268
```
257269

270+
## `disableValue`
271+
272+
By default, `<CheckboxGroupInput>` renders the choices with the field `disabled: true` as disabled.
273+
274+
```jsx
275+
const choices = [
276+
{ id: 'tech', name: 'Tech' },
277+
{ id: 'lifestyle', name: 'Lifestyle' },
278+
{ id: 'people', name: 'People', disabled: true },
279+
];
280+
<CheckboxGroupInput source="category" choices={choices} />
281+
```
282+
283+
If you want to use another field to denote disabled options, set the `disableValue` prop.
284+
285+
```jsx
286+
const choices = [
287+
{ id: 'tech', name: 'Tech' },
288+
{ id: 'lifestyle', name: 'Lifestyle' },
289+
{ id: 'people', name: 'People', not_available: true },
290+
];
291+
<CheckboxGroupInput source="category" choices={choices} disableValue="not_available" />
292+
```
293+
258294
## Fetching Choices
259295

260296
If you want to populate the `choices` attribute with a list of related records, you should decorate `<CheckboxGroupInput>` with [`<ReferenceArrayInput>`](./ReferenceArrayInput.md), and leave the `choices` empty:

packages/ra-ui-materialui/src/input/CheckboxGroupInput.spec.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,4 +426,65 @@ describe('<CheckboxGroupInput />', () => {
426426
await screen.findByText('Option 1 (This is option 1)');
427427
});
428428
});
429+
430+
it('should render disabled choices marked as so', () => {
431+
const choices = [
432+
{ id: 'ang', name: 'Angular' },
433+
{ id: 'rct', name: 'React', disabled: true },
434+
];
435+
render(
436+
<AdminContext dataProvider={testDataProvider()}>
437+
<ResourceContextProvider value="posts">
438+
<SimpleForm onSubmit={jest.fn()}>
439+
<CheckboxGroupInput
440+
{...defaultProps}
441+
choices={choices}
442+
/>
443+
</SimpleForm>
444+
</ResourceContextProvider>
445+
</AdminContext>
446+
);
447+
fireEvent.mouseDown(screen.getByLabelText('React'));
448+
449+
const enabledInput = screen.getByLabelText(
450+
'Angular'
451+
) as HTMLInputElement;
452+
expect(enabledInput.disabled).toBe(false);
453+
454+
const disabledInput = screen.getByLabelText(
455+
'React'
456+
) as HTMLInputElement;
457+
expect(disabledInput.disabled).toBe(true);
458+
});
459+
460+
it('should render disabled choices marked as so by disableValue prop', () => {
461+
const choices = [
462+
{ id: 'ang', name: 'Angular' },
463+
{ id: 'rct', name: 'React', not_available: true },
464+
];
465+
render(
466+
<AdminContext dataProvider={testDataProvider()}>
467+
<ResourceContextProvider value="posts">
468+
<SimpleForm onSubmit={jest.fn()}>
469+
<CheckboxGroupInput
470+
{...defaultProps}
471+
choices={choices}
472+
disableValue="not_available"
473+
/>
474+
</SimpleForm>
475+
</ResourceContextProvider>
476+
</AdminContext>
477+
);
478+
fireEvent.mouseDown(screen.getByLabelText('React'));
479+
480+
const enabledInput = screen.getByLabelText(
481+
'Angular'
482+
) as HTMLInputElement;
483+
expect(enabledInput.disabled).toBe(false);
484+
485+
const disabledInput = screen.getByLabelText(
486+
'React'
487+
) as HTMLInputElement;
488+
expect(disabledInput.disabled).toBe(true);
489+
});
429490
});

packages/ra-ui-materialui/src/input/CheckboxGroupInput.stories.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,17 @@ export const SetFocus = () => (
322322
<SetFocusButton source="roles" />
323323
</Wrapper>
324324
);
325+
326+
export const DisabledChoice = () => (
327+
<Wrapper>
328+
<CheckboxGroupInput
329+
source="roles"
330+
choices={[
331+
{ id: 'admin', name: 'Admin' },
332+
{ id: 'u001', name: 'Editor' },
333+
{ id: 'u002', name: 'Moderator' },
334+
{ id: 'u003', name: 'Reviewer', disabled: true },
335+
]}
336+
/>
337+
</Wrapper>
338+
);

packages/ra-ui-materialui/src/input/CheckboxGroupInput.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,23 @@ import { LinearProgress } from '../layout';
9595
* <CheckboxGroupInput source="tags" choices={choices} translateChoice={false}/>
9696
*
9797
* The object passed as `options` props is passed to the Material UI <Checkbox> components
98+
*
99+
* You can disable some choices by providing a `disableValue` field which name is `disabled` by default
100+
* @example
101+
* const choices = [
102+
* { id: 'programming', name: 'myroot.category.programming' },
103+
* { id: 'lifestyle', name: 'myroot.category.lifestyle' },
104+
* { id: 'photography', name: 'myroot.category.photography', disabled: true },
105+
* ];
106+
*
107+
* @example
108+
* const choices = [
109+
* { id: 'programming', name: 'myroot.category.programming' },
110+
* { id: 'lifestyle', name: 'myroot.category.lifestyle' },
111+
* { id: 'photography', name: 'myroot.category.photography', not_available: true },
112+
* ];
113+
* <CheckboxGroupInput source="tags" choices={choices} disableValue="not_available" />
114+
*
98115
*/
99116
export const CheckboxGroupInput = (inProps: CheckboxGroupInputProps) => {
100117
const props = useThemeProps({
@@ -124,6 +141,7 @@ export const CheckboxGroupInput = (inProps: CheckboxGroupInputProps) => {
124141
source: sourceProp,
125142
translateChoice,
126143
validate,
144+
disableValue = 'disabled',
127145
disabled,
128146
readOnly,
129147
...rest
@@ -262,6 +280,7 @@ export const CheckboxGroupInput = (inProps: CheckboxGroupInputProps) => {
262280
value={value}
263281
labelPlacement={labelPlacement}
264282
inputRef={index === 0 ? ref : undefined}
283+
disableValue={disableValue}
265284
disabled={disabled || readOnly}
266285
readOnly={readOnly}
267286
{...sanitizeRestProps(rest)}

packages/ra-ui-materialui/src/input/CheckboxGroupInputItem.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,19 @@ export const CheckboxGroupInputItem = (
3232
value,
3333
labelPlacement,
3434
inputRef,
35+
disableValue = 'disabled',
3536
...rest
3637
} = props;
3738

38-
const { getChoiceText, getChoiceValue } = useChoices({
39+
const { getChoiceText, getChoiceValue, getDisableValue } = useChoices({
3940
optionText,
4041
optionValue,
4142
translateChoice,
43+
disableValue,
4244
});
4345

4446
const choiceName = getChoiceText(choice);
47+
const disabled = getDisableValue(choice);
4548

4649
return (
4750
<StyledFormControlLabel
@@ -50,6 +53,7 @@ export const CheckboxGroupInputItem = (
5053
onChange={onChange}
5154
className={className}
5255
inputRef={inputRef}
56+
disabled={disabled}
5357
control={
5458
<Checkbox
5559
id={`${id}_${getChoiceValue(choice)}`}
@@ -74,7 +78,10 @@ export const CheckboxGroupInputItem = (
7478

7579
export interface CheckboxGroupInputItemProps
7680
extends Omit<FormControlLabelProps, 'control' | 'label'>,
77-
Pick<ChoicesProps, 'optionValue' | 'optionText' | 'translateChoice'> {
81+
Pick<
82+
ChoicesProps,
83+
'optionValue' | 'optionText' | 'translateChoice' | 'disableValue'
84+
> {
7885
choice: any;
7986
value: any;
8087
fullWidth?: boolean;

0 commit comments

Comments
 (0)