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 support for readOnly on all RA Inputs #9656

Merged
merged 58 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
2918825
add all stories
erwanMarmelab Feb 9, 2024
f3397ec
fix stories
erwanMarmelab Feb 12, 2024
12cc352
remove usless test
erwanMarmelab Feb 12, 2024
67c3731
add common test files and readOnly to textInput
erwanMarmelab Feb 12, 2024
dfe7932
fix CommonInpuProps
erwanMarmelab Feb 12, 2024
a3731ee
move common test files
erwanMarmelab Feb 12, 2024
9ab60cf
fix story imports
erwanMarmelab Feb 12, 2024
a521d26
simplify useEffect
erwanMarmelab Feb 12, 2024
f0dcdf5
move again files
erwanMarmelab Feb 12, 2024
fb1062e
build ra-data-fakerest before
erwanMarmelab Feb 12, 2024
6d5bd36
build ra-core before
erwanMarmelab Feb 12, 2024
6ba0aac
SearchInput, SelectInput, SelectArrayInput, TimeInput, TranslatableInput
erwanMarmelab Feb 12, 2024
b24de98
ReferenceInput, AutoCompleteInput
erwanMarmelab Feb 12, 2024
e403ac6
fix autocompleteInput
erwanMarmelab Feb 14, 2024
53795b1
BooleanInput + NullabeBooleanInput + CheckboxGroupInput
erwanMarmelab Feb 14, 2024
babe25d
DateInput + DateTimeInput + FileInput + ImageInput
erwanMarmelab Feb 14, 2024
15d199e
NumberInput + PasswordInput + RadioButtonGroupInput + ReferenceInput …
erwanMarmelab Feb 14, 2024
7e7301a
protect children props
erwanMarmelab Feb 14, 2024
0c542c3
simplify AutocompleteInput story, apply visual for FileInput and Imag…
erwanMarmelab Feb 14, 2024
f70b1f5
do not support readOnly and disabled for DatagridInput
erwanMarmelab Feb 14, 2024
f953859
Fix simpleFormIterator condition
erwanMarmelab Feb 15, 2024
072f907
fix tests with conditional display in SimpleFormIterator
erwanMarmelab Feb 15, 2024
57b78c5
apply Adrien's feedbacks: add disabled stories + use theme for + simp…
erwanMarmelab Feb 20, 2024
ce34218
remove readOnly from check
erwanMarmelab Feb 20, 2024
b01a31a
fix disabled condition + fix lint + fix typo
erwanMarmelab Feb 21, 2024
5294f9e
remove fullApps for console.logs
erwanMarmelab Feb 21, 2024
aadc1a3
document + remove cloning
erwanMarmelab Feb 21, 2024
e324e89
document exceptions and add BooleanInput to exceptions
erwanMarmelab Feb 21, 2024
1ea45b4
double all inputs in stories
erwanMarmelab Feb 21, 2024
2e83b7d
rollback and addition for ResettableTextField propTypes
erwanMarmelab Feb 22, 2024
fc0fdf9
remove unnecessary {% raw %}
erwanMarmelab Feb 22, 2024
3ae8c74
fix typo and apply feedbacks
erwanMarmelab Feb 22, 2024
13570ac
fix react prop declaration
erwanMarmelab Feb 22, 2024
d7fb85f
apply JB's feedbacks
erwanMarmelab Feb 26, 2024
98ba645
apply suggestion and v1 pr inputs tip modif
erwanMarmelab Feb 27, 2024
121832f
remove readOnly for nullableBooleanInput + remove useless code for Im…
erwanMarmelab Feb 27, 2024
62e96d4
fix props + Add ReadOnly for boolean, nullableBoolean, radioButtonGro…
erwanMarmelab Feb 28, 2024
e3a658e
remove disabled and readonly support for ReferenceInput
adguernier Feb 29, 2024
a19d3a4
remove disabled and readonly support for ReferenceArrayInput
adguernier Feb 29, 2024
9a40298
remove disabled and readonly support for TranslatableInput
adguernier Feb 29, 2024
9ed156c
add disabled and readonly on InputProps
adguernier Feb 29, 2024
c765c0d
pass disable and readonly to useInput in TimeInput
adguernier Feb 29, 2024
eea041f
pass disable and readonly to useInput in AutocompleteInput
adguernier Feb 29, 2024
35a8eea
pass disable and readonly to useInput in BooleanInput
adguernier Feb 29, 2024
ac421af
pass disable and readonly to useInput in CheckboxGroupInput
adguernier Feb 29, 2024
3329139
pass disable and readonly to useInput in DateInput
adguernier Feb 29, 2024
97ad021
pass disable and readonly to useInput in DateTimeInput
adguernier Feb 29, 2024
9d51cd5
pass disable and readonly to useInput in FileInput
adguernier Feb 29, 2024
3d505d0
pass disable and readonly to useInput in NullableBooleanInput
adguernier Feb 29, 2024
29427cc
pass disable and readonly to useInput in NumberInput
adguernier Feb 29, 2024
33bf13c
pass disable and readonly to useInput in RadioButtonGroupInput
adguernier Feb 29, 2024
60f0947
pass disable and readonly to useInput in SelectArrayInput
adguernier Feb 29, 2024
7b81359
remove useless mutation side effect
adguernier Feb 29, 2024
36ecea5
remove useless diff
adguernier Feb 29, 2024
88542ab
remove readonly and disabled from TranslatableInput doc
adguernier Feb 29, 2024
82a9787
clarify difference between read-only and disabled
adguernier Feb 29, 2024
c62701a
remove useless console.log
adguernier Mar 1, 2024
93572e5
Update packages/ra-ui-materialui/src/input/TimeInput.tsx
slax57 Mar 1, 2024
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ build-create-react-admin:
@echo "Transpiling create-react-admin files...";
@cd ./packages/create-react-admin && yarn build

build: build-ra-core build-ra-ui-materialui build-ra-data-fakerest build-ra-data-json-server build-ra-data-localforage build-ra-data-localstorage build-ra-data-simple-rest build-ra-data-graphql build-ra-data-graphql-simple build-ra-i18n-polyglot build-ra-input-rich-text build-data-generator build-ra-language-english build-ra-language-french build-ra-i18n-i18next build-react-admin build-ra-no-code build-create-react-admin ## compile ES6 files to JS
build: build-ra-core build-ra-data-fakerest build-ra-ui-materialui build-ra-data-json-server build-ra-data-localforage build-ra-data-localstorage build-ra-data-simple-rest build-ra-data-graphql build-ra-data-graphql-simple build-ra-i18n-polyglot build-ra-input-rich-text build-data-generator build-ra-language-english build-ra-language-french build-ra-i18n-i18next build-react-admin build-ra-no-code build-create-react-admin ## compile ES6 files to JS

doc: ## compile doc as html and launch doc web server
@yarn doc
Expand Down
25 changes: 17 additions & 8 deletions docs/Inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ All input components accept the following props:
| `source` | Required | `string` | - | Name of the entity property to use for the input value |
| `className` | Optional | `string` | - | Class name (usually generated by JSS) to customize the look and feel of the field element itself |
| `defaultValue` | Optional | `any` | - | Default value of the input. |
| `disabled` | Optional | `boolean` | - | If true, the input is disabled. |
| `readOnly` | Optional | `boolean` | `false` | If true, the input is in read-only mode. |
| `disabled` | Optional | `boolean` | `false` | If true, the input is disabled. |
| `format` | Optional | `Function` | `value => value == null ? '' : value` | Callback taking the value from the form state, and returning the input value. |
| `fullWidth` | Optional | `boolean` | `false` | If `true`, the input will expand to fill the form width |
| `helperText` | Optional | `string` | - | Text to be displayed under the input (cannot be used inside a filter) |
Expand Down Expand Up @@ -150,21 +151,29 @@ export const PostCreate = () => (
);
```

## `readOnly`

The `readOnly` prop set to true makes the element not mutable, meaning the user can not edit the control.

```tsx
<TextInput source="title" readOnly />
```

Contrary to disabled controls, read-only controls are still focusable and are submitted with the form.

## `disabled`

If `true`, the input is disabled and the user can't change the value.
The `disabled` prop set to true makes the element not mutable, focusable, or even submitted with the form.

```tsx
<TextInput source="title" disabled />
```

**Tip**: The form framework used by react-admin, react-hook-form, [considers](https://github.com/react-hook-form/react-hook-form/pull/10805) that a `disabled` input shouldn't submit any value. So react-hook-form sets the value of all `disabled` inputs to `undefined`. As a consequence, a form with a `disabled` input is always considered `dirty` (i.e. react-hook-form considers that the form values and the initial record values are different), and it triggers [the `warnWhenUnsavedChanges` feature](./EditTutorial.md#warning-about-unsaved-changes) when leaving the form, even though the user changed nothing. The workaround is to set the `disabled` prop on the underlying input component, as follows:
Contrary to read-only controls, disabled controls can not receive focus and are not submitted with the form.

{% raw %}
```jsx
<TextInput source="title" InputProps={{ disabled: true }} />
```
{% endraw %}
**Warning:** Note that `disabled` inputs are **not** included in the form values, and hence may trigger `warnWhenUnsavedChanges` if the input previously had a value in the record.

**Tip:** To include the input in the form values, you can use `readOnly` instead of `disabled`.

## `format`

Expand Down
30 changes: 30 additions & 0 deletions docs/SimpleFormIterator.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ const OrderEdit = () => (
| `inline` | Optional | `boolean` | `false` | When true, inputs are put on the same line |
| `removeButton` | Optional | `ReactElement` | - | Component to render for the remove button |
| `reOrderButtons` | Optional | `ReactElement` | - | Component to render for the up / down button |
| `readOnly` | Optional | `boolean` | `false` | If true, all inputs are in read-only mode. |
| `disabled` | Optional | `boolean` | `false` | If true, all inputs are disabled. |
| `sx` | Optional | `SxProps` | - | Material UI shortcut for defining custom styles |

## `addButton`
Expand Down Expand Up @@ -354,6 +356,34 @@ const OrderEdit = () => (
);
```

## `readOnly`

The `readOnly` prop set to true makes the children input not mutable, meaning the user can not edit them.

```jsx
<SimpleFormIterator readOnly>
<TextInput source="name" />
<NumberInput source="price" />
<NumberInput source="quantity" />
</SimpleFormIterator>
```

slax57 marked this conversation as resolved.
Show resolved Hide resolved
Contrary to disabled controls, read-only controls are still focusable and are submitted with the form.

## `disabled`

The `disabled` prop set to true makes the children input not mutable, focusable, or even submitted with the form.

```jsx
<SimpleFormIterator disabled>
<TextInput source="name" />
<NumberInput source="price" />
<NumberInput source="quantity" />
</SimpleFormIterator>
```

slax57 marked this conversation as resolved.
Show resolved Hide resolved
Contrary to read-only controls, disabled controls can not receive focus and are not submitted with the form.

## `sx`

You can override the style of the root element (a `<div>` element) as well as those of the inner components thanks to the `sx` property (see [the `sx` documentation](./SX.md) for syntax and examples).
Expand Down
2 changes: 1 addition & 1 deletion docs/TranslatableInputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,4 @@ You can add validators to any of the inputs inside a `TranslatableInputs`. If an
<TextInput source="name" validate={[required()]} />
<RichTextInput source="description" validate={[maxLength(100)]} />
</TranslatableInputs>
```
```
2 changes: 2 additions & 0 deletions packages/ra-core/src/form/useInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ export type InputProps<ValueType = any> = Omit<
resource?: string;
source: string;
validate?: Validator | Validator[];
readOnly?: boolean;
disabled?: boolean;
};

export type UseInputValue = {
Expand Down
13 changes: 13 additions & 0 deletions packages/ra-input-rich-text/src/RichTextInput.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ export const Disabled = (props: Partial<SimpleFormProps>) => (
</AdminContext>
);

export const ReadOnly = (props: Partial<SimpleFormProps>) => (
<AdminContext i18nProvider={i18nProvider}>
<SimpleForm
defaultValues={{ body: 'Hello World' }}
onSubmit={() => {}}
{...props}
>
<RichTextInput source="body" readOnly />
<FormInspector />
</SimpleForm>
</AdminContext>
);

export const Small = (props: Partial<SimpleFormProps>) => (
<AdminContext i18nProvider={i18nProvider}>
<SimpleForm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,38 @@ export const Disabled = () => (
<SimpleFormIterator>
<TextInput source="name" />
<TextInput source="role" />
<TextInput source="surname" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</Edit>
);
}}
/>
</Admin>
);

export const ReadOnly = () => (
<Admin dataProvider={dataProvider} history={history}>
<Resource
name="books"
edit={() => {
return (
<Edit
mutationMode="pessimistic"
mutationOptions={{
onSuccess: data => {
console.log(data);
},
}}
>
<SimpleForm>
<TextInput source="title" />
<ArrayInput source="authors" readOnly>
<SimpleFormIterator>
<TextInput source="name" />
<TextInput source="role" />
<TextInput source="surname" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
Expand Down Expand Up @@ -408,8 +440,8 @@ const BookEditGlobalValidation = () => {
}}
>
<SimpleForm validate={globalValidator}>
{/*
We still need `validate={required()}` to indicate fields are required
{/*
We still need `validate={required()}` to indicate fields are required
with a '*' symbol after the label, but the real validation happens in `globalValidator`
*/}
<ArrayInput source="authors" fullWidth validate={required()}>
Expand Down Expand Up @@ -438,8 +470,8 @@ const CreateGlobalValidationInFormTab = () => {
}}
>
<TabbedForm validate={globalValidator}>
{/*
We still need `validate={required()}` to indicate fields are required
{/*
We still need `validate={required()}` to indicate fields are required
with a '*' symbol after the label, but the real validation happens in `globalValidator`
*/}
<TabbedForm.Tab label="Main">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export const ArrayInput = (props: ArrayInputProps) => {
validate,
variant,
disabled,
readOnly,
margin = 'dense',
...rest
} = props;
Expand Down Expand Up @@ -185,7 +186,8 @@ export const ArrayInput = (props: ArrayInputProps) => {
source,
variant,
margin,
disabled,
disabled: children.props.disabled || disabled,
readOnly: children.props.readOnly || readOnly,
})}
</ArrayInputContext.Provider>
{renderHelperText ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,23 @@ describe('<SimpleFormIterator />', () => {
render(
<Wrapper>
<SimpleForm>
<ArrayInput source="emails" disabled>
<ArrayInput source="emails" disabled readOnly={false}>
<SimpleFormIterator>
<TextInput source="email" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</Wrapper>
);

expect(screen.queryAllByLabelText('ra.action.add').length).toBe(0);
});

it('should not display add button if readOnly is truthy', () => {
render(
<Wrapper>
<SimpleForm>
<ArrayInput source="emails" readOnly>
<SimpleFormIterator>
<TextInput source="email" />
</SimpleFormIterator>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,38 @@ export const Inline = () => (
</AdminContext>
);

export const ReadOnly = () => (
<AdminContext dataProvider={dataProvider}>
<Edit resource="books" id="1">
<SimpleForm>
<ArrayInput source="authors">
<SimpleFormIterator readOnly>
<TextInput source="name" />
<TextInput source="role" />
<TextInput source="surname" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</Edit>
</AdminContext>
);

export const Disabled = () => (
<AdminContext dataProvider={dataProvider}>
<Edit resource="books" id="1">
<SimpleForm>
<ArrayInput source="authors">
<SimpleFormIterator disabled>
<TextInput source="name" />
<TextInput source="role" />
<TextInput source="surname" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</Edit>
</AdminContext>
);

export const DisableAdd = () => (
<AdminContext dataProvider={dataProvider}>
<Edit resource="books" id="1">
Expand Down
Loading
Loading