Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix <RadioButtonGroupInput options> prop was ignored #8299

Merged
merged 25 commits into from
Oct 25, 2022
Merged
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d79a739
[Doc] Improve SelectInput docs
fzaninotto Oct 24, 2022
c423ce5
Improve RadioButtonGroupInput doc
fzaninotto Oct 24, 2022
7e864f6
Improve AutocompleteInput docs
fzaninotto Oct 24, 2022
c4ad534
Update AutocompleteInput illustration
fzaninotto Oct 24, 2022
9daef72
Merge branch 'master' into doc-inputs
fzaninotto Oct 24, 2022
8e8694d
Add useInput chapter
fzaninotto Oct 24, 2022
5c226f0
Add input component zoo
fzaninotto Oct 24, 2022
790e4c2
Tweak AutocompleteInput custom element tutorial
fzaninotto Oct 24, 2022
9760c32
Improve ReferenceInput documentation
fzaninotto Oct 24, 2022
e72205d
Fix DualListInput doc
fzaninotto Oct 24, 2022
786dba6
Add relationship explanation to ReferenceInput
fzaninotto Oct 24, 2022
70a2ff7
Improve ReferenceInput doc again
fzaninotto Oct 24, 2022
d945e59
final tweaks
fzaninotto Oct 24, 2022
27ad173
Update docs/RadioButtonGroupInput.md
fzaninotto Oct 25, 2022
e105e68
Update docs/RadioButtonGroupInput.md
fzaninotto Oct 25, 2022
f77aade
Add defaultValue
fzaninotto Oct 25, 2022
b612f40
Update docs/RadioButtonGroupInput.md
fzaninotto Oct 25, 2022
224676c
Update docs/Inputs.md
fzaninotto Oct 25, 2022
7dfdce4
Update docs/useInput.md
fzaninotto Oct 25, 2022
b57fb86
Update docs/ReferenceInput.md
fzaninotto Oct 25, 2022
9233142
Update docs/ReferenceInput.md
fzaninotto Oct 25, 2022
5feb550
Update docs/SelectInput.md
fzaninotto Oct 25, 2022
5a20c29
Update docs/AutocompleteInput.md
fzaninotto Oct 25, 2022
1ea0ee1
Update docs/AutocompleteInput.md
fzaninotto Oct 25, 2022
4e104b2
Update docs/AutocompleteInput.md
fzaninotto Oct 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 187 additions & 33 deletions docs/RadioButtonGroupInput.md
Original file line number Diff line number Diff line change
@@ -5,27 +5,52 @@ title: "The RadioButtonGroupInput Component"

# `<RadioButtonGroupInput>`

If you want to let the user choose a value among a list of possible values that are always shown (instead of hiding them behind a dropdown list, as in [`<SelectInput>`](./SelectInput.md)), `<RadioButtonGroupInput>` is the right component.
If you want to let the user choose a value among a list of possible values that are always shown, `<RadioButtonGroupInput>` is the right component. It renders using [MUI's `<RadioGroup>`](https://mui.com/material-ui/react-radio-button/).

![RadioButtonGroupInput](./img/radio-button-group-input.gif)

Set the `choices` attribute to determine the options (with `id`, `name` tuples):
This input allows editing record fields that are scalar values, e.g. `123`, `'admin'`, etc.

## Usage

In addition to the `source`, `<RadioButtonGroupInput>` requires one prop: the `choices` listing the possible values.

```jsx
import { RadioButtonGroupInput } from 'react-admin';

<RadioButtonGroupInput source="category" choices={[
{ id: 'programming', name: 'Programming' },
{ id: 'tech', name: 'Tech' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'photography', name: 'Photography' },
{ id: 'people', name: 'People' },
]} />
```

## Properties
By default, the possible choices are built from the `choices` prop, using:
- the `id` field as the option value,
- the `name` field as the option text

The form value for the source must be the selected value, e.g.

```js
{
id: 123,
title: 'Lorem Ipsum',
category: 'lifestyle',
}
```

**Tip**: React-admin includes other components to edit such values:

- [`<SelectInput>`](./SelectInput.md) renders a dropdown
- [`<AutocompleteInput>`](./AutocompleteInput.md) renders a list of suggestions in an autocomplete input

**Tip**: If you need to let users select more than one item in the list, check out the [`<CheckboxGroupInput>`](./CheckboxGroupInput.md) component.

## Props

| Prop | Required | Type | Default | Description |
| ----------------- | -------- | -------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `choices` | Required | `Object[]` | - | List of items to show as options |
| `choices` | Optional | `Object[]` | - | List of items to show as options. Required unless inside a ReferenceInput.s |
| `options` | Optional | `Object` | - | Props to pass to the underlying `<RadioButtonGroup>` element |
| `optionText` | Optional | `string` &#124; `Function` | `name` | Field name of record to display in the suggestion item or function which accepts the current record as argument (`record => {string}`) |
| `optionValue` | Optional | `string` | `id` | Field name of record containing the value to use as input value |
@@ -34,68 +59,96 @@ import { RadioButtonGroupInput } from 'react-admin';

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

## Usage
## `choices`

You can customize the properties to use for the option name and value, thanks to the `optionText` and `optionValue` attributes:
An array of objects that represents the choices to show in the options. The objects must have at least two fields: one to use for the option name, and the other to use for the option value. By default, `<RadioButtonGroupInput>` will use the `id` and `name` fields.

```jsx
const choices = [
{ _id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
{ _id: 456, full_name: 'Jane Austen', sex: 'F' },
{ id: 'tech', name: 'Tech' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'people', name: 'People' },
];
<RadioButtonGroupInput source="author_id" choices={choices} optionText="full_name" optionValue="_id" />
<RadioButtonGroupInput source="category" choices={choices} />
```

`optionText` also accepts a function, so you can shape the option text at will:
If the choices have different keys, you can use [`optionText`](#optiontext) and [`optionValue`](#optionvalue) to specify which fields to use for the name and value.

```jsx
const choices = [
{ id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
{ id: 456, first_name: 'Jane', last_name: 'Austen' },
{ _id: 'tech', label: 'Tech' },
{ _id: 'lifestyle', label: 'Lifestyle' },
{ _id: 'people', label: 'People' },
];
const optionRenderer = choice => `${choice.first_name} ${choice.last_name}`;
<RadioButtonGroupInput source="author_id" choices={choices} optionText={optionRenderer} />
<RadioButtonGroupInput
source="category"
choices={choices}
optionText="label"
optionValue="_id"
/>
```

`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.
The choices are translated by default, so you can use translation identifiers as choices:

```jsx
const choices = [
{ id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
{ id: 456, first_name: 'Jane', last_name: 'Austen' },
{ id: 'tech', name: 'myroot.categories.tech' },
{ id: 'lifestyle', name: 'myroot.categories.lifestyle' },
{ id: 'people', name: 'myroot.categories.people' },
];
const FullNameField = ({ record }) => <span>{record.first_name} {record.last_name}</span>;
<RadioButtonGroupInput source="gender" choices={choices} optionText={<FullNameField />}/>
```

The choices are translated by default, so you can use translation identifiers as choices:
You can opt-out of this translation by setting [the `translateChoice` prop](#translatechoice) to `false`.

If you need to *fetch* the options from another resource, you're actually editing a many-to-one or a one-to-one relationship. In this case, wrap the `<RadioButtonGroupInput>` in a [`<ReferenceInput>`](./ReferenceInput.md). You don't need to specify the `choices` prop - the parent component injects it based on the possible values of the related resource.

```jsx
const choices = [
{ id: 'M', name: 'myroot.gender.male' },
{ id: 'F', name: 'myroot.gender.female' },
];
<ReferenceInput label="Author" source="author_id" reference="authors">
<RadioButtonGroupInput />
</ReferenceInput>
```

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`.
See [Using in a `ReferenceInput>`](#using-in-a-referenceinput) below for more information.

If you have an *array of values* for the options, turn it into an array of objects with the `id` and `name` properties:

```jsx
<RadioButtonGroupInput source="gender" choices={choices} translateChoice={false}/>
const possibleValues = ['tech', 'lifestyle', 'people'];
const ucfirst = name => name.charAt(0).toUpperCase() + name.slice(1);
const choices = possibleValues.map(value => ({ id: value, name: ucfirst(value) }));

<RadioButtonGroupInput source="category" choices={choices} />
```

Lastly, use the `options` attribute if you want to override any of MUI's `<RadioButtonGroup>` attributes:
## `options`

Use the `options` attribute if you want to override any of MUI's `<RadioButtonGroup>` attributes:

{% raw %}
```jsx
<RadioButtonGroupInput source="category" options={{
labelPosition: 'right'
}} />
<RadioButtonGroupInput
source="category"
choices={choices}
options={{ labelPosition: 'right' }} />
```
{% endraw %}

Refer to [MUI RadioGroup documentation](https://mui.com/api/radio-group) for more details.

**Tip**: If you want to populate the `choices` attribute with a list of related records, you should decorate `<RadioButtonGroupInput>` with [`<ReferenceInput>`](./ReferenceInput.md), and leave the `choices` empty:
## `optionText`

You can customize the property to use for the option name (instead of the default `name`) thanks to the `optionText` prop:

```jsx
const choices = [
{ id: 'tech', label: 'Tech' },
{ id: 'lifestyle', label: 'Lifestyle' },
{ id: 'people', label: 'People' },
];
<RadioButtonGroupInput source="category" choices={choices} optionText="label" />
```

`optionText` is particularly useful when the choices are records fetched from another resource, and `<RadioButtonGroupInput>` is a child of a [`<ReferenceInput>`](./ReferenceInput.md). 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.

```jsx
import { RadioButtonGroupInput, ReferenceInput } from 'react-admin';
@@ -105,6 +158,66 @@ import { RadioButtonGroupInput, ReferenceInput } from 'react-admin';
</ReferenceInput>
```

See [Using in a `<ReferenceInput>`](#using-in-a-referenceinput) below for more details.

`optionText` also accepts a function, so you can shape the option text at will:

```jsx
const choices = [
{ id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
{ id: 456, first_name: 'Jane', last_name: 'Austen' },
];
const optionRenderer = choice => `${choice.first_name} ${choice.last_name}`;
<RadioButtonGroupInput
source="author_id"
choices={choices}
optionText={optionRenderer}
/>
```

`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.

```jsx
const choices = [
{ id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
{ id: 456, first_name: 'Jane', last_name: 'Austen' },
];

const FullNameField = () => {
const record = useRecordContext();
return <span>{record.first_name} {record.last_name}</span>;
}

<RadioButtonGroupInput source="author_id" choices={choices} optionText={<FullNameField />}/>
```

## `optionValue`

You can customize the property to use for the option value (instead of the default `id`) thanks to the `optionValue` prop:

```jsx
const choices = [
{ _id: 'tech', name: 'Tech' },
{ _id: 'lifestyle', name: 'Lifestyle' },
{ _id: 'people', name: 'People' },
];
<RadioButtonGroupInput
source="category"
choices={choices}
optionValue="_id"
/>
```

## `row`

By default, the radio buttons 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`:

```jsx
<RadioButtonGroupInput source="category" choices={choices} row={false} />
```

![RadioButtonGroupInput row false](./img/radio-button-group-input-row.gif)

## `sx`: CSS API

The `<RadioButtonGroupInput>` component accepts the usual `className` prop. You can also override many styles of the inner components thanks to the `sx` property (as most MUI components, see their [documentation about it](https://mui.com/customization/how-to-customize/#overriding-nested-component-styles)). This property accepts the following subclasses:
@@ -114,3 +227,44 @@ The `<RadioButtonGroupInput>` component accepts the usual `className` prop. You
| `& .RaRadioButtonGroupInput-label` | Applied to the underlying MUI's `FormLabel` component |

To override the style of all instances of `<RadioButtonGroupInput>` using the [MUI style overrides](https://mui.com/customization/globals/#css), use the `RaRadioButtonGroupInput` key.

## `translateChoice`

The choices are translated by default, so you can use translation identifiers as choices:

```jsx
const choices = [
{ id: 'M', name: 'myroot.gender.male' },
{ id: 'F', name: 'myroot.gender.female' },
];
```

However, in some cases, you may not want the choice to be translated. In that case, set the `translateChoice` prop to `false`.

```jsx
<RadioButtonGroupInput source="gender" choices={choices} translateChoice={false}/>
```

Note that `translateChoice` is set to `false` when `<RadioButtonGroupInput>` is a child of `<ReferenceInput>`.

## Using In A ReferenceInput

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

```jsx
import { RadioButtonGroupInput, ReferenceInput } from 'react-admin';

<ReferenceInput label="Author" source="author_id" reference="authors">
<RadioButtonGroupInput />
</ReferenceInput>
```

In that case, `<RadioButtonGroupInput>` uses the [`recordRepresentation`](./Resource.md#recordrepresentation) to render each choice from the list of possible records. You can override this behavior by setting the `optionText` prop:

```jsx
import { RadioButtonGroupInput, ReferenceInput } from 'react-admin';

<ReferenceInput label="Author" source="author_id" reference="authors">
<RadioButtonGroupInput optionText="last_name" />
</ReferenceInput>
```
22 changes: 11 additions & 11 deletions docs/SelectInput.md
Original file line number Diff line number Diff line change
@@ -11,13 +11,6 @@ To let users choose a value in a list using a dropdown, use `<SelectInput>`. It

This input allows editing record fields that are scalar values, e.g. `123`, `'admin'`, etc.

**Tip**: React-admin includes other components allowing the edition of such values:

- [`<RadioButtonGroupInput>`](./RadioButtonGroupInput.md) renders a list of radio buttons
- [`<AutocompleteInput>`](./AutocompleteInput.md) renders a list of suggestions in an autocomplete input

**Tip**: If you need to let users select more than one item in the list, check out the [`<SelectArrayInput>`](./SelectArrayInput.md) component.

## Usage

In addition to the `source`, `<SelectInput>` requires one prop: the `choices` listing the possible values.
@@ -46,11 +39,18 @@ The form value for the source must be the selected value, e.g.
}
```

**Tip**: React-admin includes other components to edit such values:

- [`<RadioButtonGroupInput>`](./RadioButtonGroupInput.md) renders a list of radio buttons
- [`<AutocompleteInput>`](./AutocompleteInput.md) renders a list of suggestions in an autocomplete input

**Tip**: If you need to let users select more than one item in the list, check out the [`<SelectArrayInput>`](./SelectArrayInput.md) component.

## Props

| Prop | Required | Type | Default | Description |
|-------------------|----------|----------------------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| `choices` | Optional | `Object[]` | - | List of items to show as options. Required if not inside a ReferenceInput. |
| `choices` | Optional | `Object[]` | - | List of items to show as options. Required unless inside a ReferenceInput. |
| `create` | Optional | `Element` | `-` | A React Element to render when users want to create a new choice |
| `createLabel` | Optional | `string` | `ra.action.create` | The label for the menu item allowing users to create a new choice. Used when the filter is empty |
| `disableValue` | Optional | `string` | 'disabled' | The custom field name used in `choices` to disable some choices |
@@ -323,7 +323,7 @@ Refer to [MUI Select documentation](https://mui.com/api/select) for more details

## `optionText`

You can customize the choice field to use for the option name, thanks to the `optionText` attribute:
You can customize the property to use for the option name (instead of the default `name`) thanks to the `optionText` prop:

```jsx
const choices = [
@@ -370,12 +370,12 @@ const FullNameField = () => {
return <span>{record.first_name} {record.last_name}</span>;
}

<SelectInput source="gender" choices={choices} optionText={<FullNameField />}/>
<SelectInput source="author_id" choices={choices} optionText={<FullNameField />}/>
```

## `optionValue`

You can customize the choice field to use for the option value, thanks to the `optionValue` attribute:
You can customize the property to use for the option value (instead of the default `id`) thanks to the `optionValue` prop:

```jsx
const choices = [
Binary file added docs/img/radio-button-group-input-row.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/radio-button-group-input.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -10,14 +10,42 @@ import { FormInspector } from './common.stories';

export default { title: 'ra-ui-materialui/input/RadioButtonGroupInput' };

const choices = [
{ id: 'M', name: 'Male' },
{ id: 'F', name: 'Female' },
];

export const Basic = () => (
<Wrapper>
<RadioButtonGroupInput choices={choices} source="gender" />
<RadioButtonGroupInput
source="category"
choices={[
{ id: 'tech', name: 'Tech' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'people', name: 'People' },
]}
/>
</Wrapper>
);

export const Row = () => (
<Wrapper>
<RadioButtonGroupInput
source="category"
choices={[
{ id: 'tech', name: 'Tech' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'people', name: 'People' },
]}
row={false}
/>
</Wrapper>
);

export const DefaultValue = () => (
<Wrapper>
<RadioButtonGroupInput
choices={[
{ id: 'M', name: 'Male' },
{ id: 'F', name: 'Female' },
]}
source="gender"
/>
</Wrapper>
);

3 changes: 3 additions & 0 deletions packages/ra-ui-materialui/src/input/RadioButtonGroupInput.tsx
Original file line number Diff line number Diff line change
@@ -95,6 +95,7 @@ export const RadioButtonGroupInput = (props: RadioButtonGroupInputProps) => {
margin = 'dense',
onBlur,
onChange,
options,
optionText,
optionValue,
parse,
@@ -182,6 +183,7 @@ export const RadioButtonGroupInput = (props: RadioButtonGroupInputProps) => {
id={id}
row={row}
{...field}
{...options}
{...sanitizeRestProps(rest)}
>
{allChoices.map(choice => (
@@ -271,6 +273,7 @@ export type RadioButtonGroupInputProps = Omit<CommonInputProps, 'source'> &
ChoicesProps &
FormControlProps &
RadioGroupProps & {
options?: RadioGroupProps;
source?: string;
};