Skip to content

Commit 2e47d9d

Browse files
authored
Merge pull request #8291 from marmelab/doc-checkboaxgroupinput
Fix `<CheckboxGroupInput options>` prop is ignored
2 parents ff63961 + 040f54d commit 2e47d9d

7 files changed

+237
-48
lines changed

docs/CheckboxGroupInput.md

+181-43
Original file line numberDiff line numberDiff line change
@@ -7,96 +7,215 @@ title: "The CheckboxGroupInput Component"
77

88
If you want to let the user choose multiple values among a list of possible values by showing them all, `<CheckboxGroupInput>` is the right component.
99

10-
![CheckboxGroupInput](./img/checkbox-group-input.png)
10+
![CheckboxGroupInput](./img/checkbox-group-input.gif)
1111

12-
Set the `choices` attribute to determine the options (with `id`, `name` tuples):
12+
This input allows editing values that are arrays of scalar values, e.g. `[123, 456]`.
13+
14+
**Tip**: React-admin includes other components allowing the edition of such values:
15+
16+
- [`<SelectArrayInput>`](./SelectArrayInput.md) renders a dropdown list of choices
17+
- [`<AutocompleteArrayInput>`](./AutocompleteArrayInput.md) renders an autocomplete input of choices
18+
19+
And if you are looking for a way to edit a list of embedded objects (e.g. `[{ id: 123, title: 'Hello' }, { id: 456, title: 'World' }]`), check the [`<ArrayInput>`](./ArrayInput.md) component.
20+
21+
## Usage
22+
23+
In addition to the `source`, `<CheckboxGroupInput>` requires one prop: the `choices` listing the possible values.
1324

1425
```jsx
1526
import { CheckboxGroupInput } from 'react-admin';
1627

17-
<CheckboxGroupInput source="category" choices={[
18-
{ id: 'programming', name: 'Programming' },
19-
{ id: 'lifestyle', name: 'Lifestyle' },
20-
{ id: 'photography', name: 'Photography' },
28+
<CheckboxGroupInput source="roles" choices={[
29+
{ id: 'admin', name: 'Admin' },
30+
{ id: 'u001', name: 'Editor' },
31+
{ id: 'u002', name: 'Moderator' },
32+
{ id: 'u003', name: 'Reviewer' },
2133
]} />
2234
```
2335

24-
## Properties
36+
By default, the possible choices are built from the `choices` prop, using:
37+
- the `id` field as the option value,
38+
- the `name` field as the option text
2539

26-
| Prop | Required | Type | Default | Description |
27-
| ------------- | -------- | -------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |
28-
| `choices` | Required | `Object[]` | - | List of choices |
29-
| `optionText` | Optional | `string` &#124; `Function` | `name` | Field name of record to display in the suggestion item or function which accepts the correct record as argument (`record => {string}`) |
30-
| `optionValue` | Optional | `string` | `id` | Field name of record containing the value to use as input value |
31-
| `row` | Optional | `boolean` | `true` | Display group of elements in a compact row. |
32-
| `labelPlacement` | Optional | `"bottom" `&#124;`"end"`&#124;`"start"`&#124;`"top" ` | `"end"` | The position of the checkbox label. |
40+
The form value for the source must be an array of the selected values, e.g.
3341

34-
Refer to [MUI Checkbox documentation](https://mui.com/api/checkbox/) for more details.
42+
```js
43+
{
44+
id: 123,
45+
name: 'John Doe',
46+
roles: ['u001', 'u003'],
47+
}
48+
```
49+
50+
## Props
51+
52+
| Prop | Required | Type | Default | Description |
53+
| ----------------- | -------- | -------------------------- | ------- | ----------------------------------------------------------------- |
54+
| `choices` | Required | `Object[]` | - | List of choices |
55+
| `labelPlacement` | Optional | `"bottom" `&#124;`"end"`&#124;`"start"`&#124;`"top" ` | `"end"` | The position of the checkbox label. |
56+
| `options` | Optional | `Object` | - | Props to pass to the MUI `<CheckboxGroup>` component. |
57+
| `optionText` | Optional | `string` &#124; `Function` | `name` | Field name of record to display in the suggestion item or function which accepts the correct record as argument (`record => {string}`) |
58+
| `optionValue` | Optional | `string` | `id` | Field name of record containing the value to use as input value |
59+
| `row` | Optional | `boolean` | `true` | Display group of elements in a compact row. |
60+
| `translateChoice` | Optional | `boolean` | `true` | Whether the choices should be translated |
3561

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

38-
## Usage
64+
## `choices`
65+
66+
The list of choices must be an array of objects - one object for each possible choice. In each object, `id` is the value, and the `name` is the label displayed to the user.
67+
68+
```jsx
69+
<CheckboxGroupInput source="roles" choices={[
70+
{ id: 'admin', name: 'Admin' },
71+
{ id: 'u001', name: 'Editor' },
72+
{ id: 'u002', name: 'Moderator' },
73+
{ id: 'u003', name: 'Reviewer' },
74+
]} />
75+
```
76+
77+
You can also use an array of objects with different properties for the label and value, given you specify the `optionText` and `optionValue` props:
78+
79+
```jsx
80+
<CheckboxGroupInput source="roles" choices={[
81+
{ _id: 'admin', label: 'Admin' },
82+
{ _id: 'u001', label: 'Editor' },
83+
{ _id: 'u002', label: 'Moderator' },
84+
{ _id: 'u003', label: 'Reviewer' },
85+
]} optionValue="_id" optionText="label" />
86+
```
87+
88+
The choices are translated by default, so you can use translation identifiers as choices:
89+
90+
```jsx
91+
const choices = [
92+
{ id: 'admin', label: 'myroot.roles.admin' },
93+
{ id: 'u001', label: 'myroot.roles.u001' },
94+
{ id: 'u002', label: 'myroot.roles.u002' },
95+
{ id: 'u003', label: 'myroot.roles.u003' },
96+
];
97+
```
98+
99+
You can opt-out of this translation by setting [the `translateChoice` prop](#translatechoice) to `false`.
100+
101+
If you need to *fetch* the options from another resource, you're actually editing a one-to-many or a many-to-many relationship. In this case, wrap the `<CheckboxGroupInput>` in a [`<ReferenceArrayInput>`](./ReferenceArrayInput.md) or a [`<ReferenceManyToManyInput>`](./ReferenceManyToManyInput.md) component. You don't need to specify the `choices` prop - the parent component injects it based on the possible values of the related resource.
102+
103+
```jsx
104+
<ReferenceArrayInput source="tag_ids" reference="tags">
105+
<CheckboxGroupInput />
106+
</ReferenceArrayInput>
107+
```
108+
109+
If you have an *array of values* for the options, turn it into an array of objects with the `id` and `name` properties:
110+
111+
```jsx
112+
const possibleValues = ['programming', 'lifestyle', 'photography'];
113+
const ucfirst = name => name.charAt(0).toUpperCase() + name.slice(1);
114+
const choices = possibleValues.map(value => ({ id: value, name: ucfirst(value) }));
115+
116+
<CheckboxGroupInput source="roles" choices={choices} />
117+
```
118+
119+
## `labelPlacement`
120+
121+
By default, this inputs renders a checkbox and a label for each choice, with the label on the right of the checkbox. You can change this behavior with the `labelPlacement` prop:
122+
123+
```jsx
124+
<CheckboxGroupInput source="options" choices={choices} labelPlacement="bottom" />
125+
```
126+
127+
![labelPlacement bottom](./img/CheckboxGroupInput-labelPlacement.png)
128+
129+
## `options`
130+
131+
Use the `options` attribute if you want to override any of MUI's [MUI Checkbox documentation](https://mui.com/api/checkbox/) attributes:
39132

40-
You can customize the properties to use for the option name and value, thanks to the `optionText` and `optionValue` attributes:
133+
{% raw %}
134+
```jsx
135+
import { FavoriteBorder, Favorite } from '@mui/icons-material';
136+
137+
<CheckboxGroupInput source="options" options={{
138+
icon: <FavoriteBorder />,
139+
checkedIcon: <Favorite />
140+
}} />
141+
```
142+
{% endraw %}
143+
144+
![row bottom](./img/CheckboxGroupInput-options.png)
145+
146+
## `optionText`
147+
148+
You can customize the properties to use for the option name (instead of the default `name`) thanks to the `optionText` prop:
41149

42150
```jsx
43151
const choices = [
44-
{ _id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
45-
{ _id: 456, full_name: 'Jane Austen', sex: 'F' },
152+
{ id: 'admin', label: 'Admin' },
153+
{ id: 'u001', label: 'Editor' },
154+
{ id: 'u002', label: 'Moderator' },
155+
{ id: 'u003', label: 'Reviewer' },
46156
];
47-
<CheckboxGroupInput source="author_id" choices={choices} optionText="full_name" optionValue="_id" />
157+
<CheckboxGroupInput source="roles" choices={choices} optionText="label" />
158+
```
159+
160+
`optionText` is especially useful when the choices are records coming from a `<ReferenceArrayInput>` or a `<ReferenceManyToManyInput>`. By default, react-admin uses the [`recordRepresentation`](./Resource.md#recordrepresentation) function to display the record label. But if you set the `optionText` prop, react-admin will use it instead.
161+
162+
```jsx
163+
<ReferenceArrayInput source="tag_ids" reference="tags">
164+
<CheckboxGroupInput optionText="tag" />
165+
</ReferenceArrayInput>
48166
```
49167

50-
`optionText` also accepts a function, so you can shape the option text at will:
168+
`optionText` also accepts a function, so you can shape the option text based on the entire choice object:
51169

52170
```jsx
53171
const choices = [
54172
{ id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
55173
{ id: 456, first_name: 'Jane', last_name: 'Austen' },
56174
];
57175
const optionRenderer = choice => `${choice.first_name} ${choice.last_name}`;
58-
<CheckboxGroupInput source="author_id" choices={choices} optionText={optionRenderer} />
176+
177+
<CheckboxGroupInput source="authors" choices={choices} optionText={optionRenderer} />
59178
```
60179

61-
`optionText` also accepts a React Element, that will be cloned and receive the related choice as the `record` prop. You can use Field components there.
180+
`optionText` also accepts a React Element, that will be rendered inside a [`<RecordContext>`](./useRecordContext.md) using the related choice as the `record` prop. You can use Field components there.
62181

63182
```jsx
64183
const choices = [
65184
{ id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
66185
{ id: 456, first_name: 'Jane', last_name: 'Austen' },
67186
];
68-
const FullNameField = ({ record }) => <span>{record.first_name} {record.last_name}</span>;
69-
<CheckboxGroupInput source="gender" choices={choices} optionText={<FullNameField />}/>
187+
188+
const FullNameField = () => {
189+
const record = useRecordContext();
190+
return <span>{record.first_name} {record.last_name}</span>;
191+
}
192+
193+
<CheckboxGroupInput source="authors" choices={choices} optionText={<FullNameField />}/>
70194
```
71195

72-
The choices are translated by default, so you can use translation identifiers as choices:
196+
## `optionValue`
197+
198+
You can customize the properties to use for the option value (instead of the default `id`) thanks to the `optionValue` prop:
73199

74200
```jsx
75201
const choices = [
76-
{ id: 'programming', name: 'myroot.category.programming' },
77-
{ id: 'lifestyle', name: 'myroot.category.lifestyle' },
78-
{ id: 'photography', name: 'myroot.category.photography' },
202+
{ _id: 'admin', name: 'Admin' },
203+
{ _id: 'u001', name: 'Editor' },
204+
{ _id: 'u002', name: 'Moderator' },
205+
{ _id: 'u003', name: 'Reviewer' },
79206
];
207+
<CheckboxGroupInput source="roles" choices={choices} optionValue="_id" />
80208
```
81209

82-
However, in some cases (e.g. inside a `<ReferenceInput>`), you may not want the choice to be translated. In that case, set the `translateChoice` prop to `false`.
83-
84-
```jsx
85-
<CheckboxGroupInput source="gender" choices={choices} translateChoice={false}/>
86-
```
210+
## `row`
87211

88-
Lastly, use the `options` attribute if you want to override any of MUI's `<Checkbox>` attributes:
212+
By default, the checkboxes are displayed in a row. You can change that and let react-admin render one choice per row by setting the `row` prop to `false`:
89213

90-
{% raw %}
91214
```jsx
92-
import { FavoriteBorder, Favorite } from '@mui/icons-material';
93-
94-
<CheckboxGroupInput source="category" options={{
95-
icon: <FavoriteBorder />,
96-
checkedIcon: <Favorite />
97-
}} />
215+
<CheckboxGroupInput source="options" choices={choices} row={false} />
98216
```
99-
{% endraw %}
217+
218+
![row bottom](./img/CheckboxGroupInput-row.png)
100219

101220
## `sx`: CSS API
102221

@@ -107,3 +226,22 @@ The `<CheckboxGroupInput>` component accepts the usual `className` prop. You can
107226
| `& .RaCheckboxGroupInput-label` | Applied to the underlying MUI's `FormLabel` component |
108227

109228
To override the style of all instances of `<CheckboxGroupInput>` using the [MUI style overrides](https://mui.com/customization/globals/#css), use the `RaCheckboxGroupInput` key.
229+
230+
## `translateChoice`
231+
232+
The choices are translated by default, so you can use translation identifiers as choices:
233+
234+
```jsx
235+
const choices = [
236+
{ id: 'admin', label: 'myroot.roles.admin' },
237+
{ id: 'u001', label: 'myroot.roles.u001' },
238+
{ id: 'u002', label: 'myroot.roles.u002' },
239+
{ id: 'u003', label: 'myroot.roles.u003' },
240+
];
241+
```
242+
243+
However, in some cases (e.g. inside a `<ReferenceArrayInput>`), you may not want the choice to be translated. In that case, set the `translateChoice` prop to `false`.
244+
245+
```jsx
246+
<CheckboxGroupInput source="roles" choices={choices} translateChoice={false}/>
247+
```
88.3 KB
Loading
97.3 KB
Loading

docs/img/CheckboxGroupInput-row.png

154 KB
Loading

docs/img/checkbox-group-input.gif

83.1 KB
Loading

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

+52-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import * as React from 'react';
22
import polyglotI18nProvider from 'ra-i18n-polyglot';
33
import englishMessages from 'ra-language-english';
4+
import { Typography } from '@mui/material';
5+
import { FavoriteBorder, Favorite } from '@mui/icons-material';
6+
import { testDataProvider, useRecordContext } from 'ra-core';
47

58
import { AdminContext } from '../AdminContext';
69
import { Create } from '../detail';
710
import { SimpleForm } from '../form';
811
import { CheckboxGroupInput } from './CheckboxGroupInput';
9-
import { Typography } from '@mui/material';
10-
import { testDataProvider, useRecordContext } from 'ra-core';
1112
import { ReferenceArrayInput } from './ReferenceArrayInput';
1213

1314
export default { title: 'ra-ui-materialui/input/CheckboxGroupInput' };
@@ -27,11 +28,19 @@ export const Basic = () => (
2728
<AdminContext i18nProvider={i18nProvider}>
2829
<Create
2930
resource="posts"
30-
record={{ options: [1, 2] }}
31+
record={{ roles: ['u001', 'u003'] }}
3132
sx={{ width: 600 }}
3233
>
3334
<SimpleForm>
34-
<CheckboxGroupInput source="options" choices={choices} />
35+
<CheckboxGroupInput
36+
source="roles"
37+
choices={[
38+
{ id: 'admin', name: 'Admin' },
39+
{ id: 'u001', name: 'Editor' },
40+
{ id: 'u002', name: 'Moderator' },
41+
{ id: 'u003', name: 'Reviewer' },
42+
]}
43+
/>
3544
</SimpleForm>
3645
</Create>
3746
</AdminContext>
@@ -80,6 +89,24 @@ export const Disabled = () => (
8089
</AdminContext>
8190
);
8291

92+
export const LabelPlacement = () => (
93+
<AdminContext i18nProvider={i18nProvider}>
94+
<Create
95+
resource="posts"
96+
record={{ options: [1, 2] }}
97+
sx={{ width: 600 }}
98+
>
99+
<SimpleForm>
100+
<CheckboxGroupInput
101+
source="options"
102+
choices={choices}
103+
labelPlacement="bottom"
104+
/>
105+
</SimpleForm>
106+
</Create>
107+
</AdminContext>
108+
);
109+
83110
export const Column = () => (
84111
<AdminContext i18nProvider={i18nProvider}>
85112
<Create
@@ -98,6 +125,27 @@ export const Column = () => (
98125
</AdminContext>
99126
);
100127

128+
export const Options = () => (
129+
<AdminContext i18nProvider={i18nProvider}>
130+
<Create
131+
resource="posts"
132+
record={{ options: [1, 2] }}
133+
sx={{ width: 600 }}
134+
>
135+
<SimpleForm>
136+
<CheckboxGroupInput
137+
source="options"
138+
choices={choices}
139+
options={{
140+
icon: <FavoriteBorder />,
141+
checkedIcon: <Favorite />,
142+
}}
143+
/>
144+
</SimpleForm>
145+
</Create>
146+
</AdminContext>
147+
);
148+
101149
export const CustomOptionText = () => (
102150
<AdminContext i18nProvider={i18nProvider}>
103151
<Create

0 commit comments

Comments
 (0)