Skip to content

Commit

Permalink
Merge pull request #5618 from marmelab/ArrayInput-disabled
Browse files Browse the repository at this point in the history
Add support for disabled in ArrayInput
  • Loading branch information
djhi authored Dec 3, 2020
2 parents e46c682 + 2e159c7 commit 1ef2add
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 18 deletions.
106 changes: 106 additions & 0 deletions packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { cleanup, fireEvent, wait, getByText } from '@testing-library/react';
import * as React from 'react';
import expect from 'expect';
import {
renderWithRedux,
SaveContextProvider,
Expand Down Expand Up @@ -29,6 +30,68 @@ describe('<SimpleFormIterator />', () => {
const saveContextValue = { save: jest.fn(), saving: false };
const sideEffectValue = {};

it('should display one input group per row', () => {
const { queryAllByLabelText } = renderWithRedux(
<ThemeProvider theme={theme}>
<SaveContextProvider value={saveContextValue}>
<SideEffectContextProvider value={sideEffectValue}>
<SimpleForm
record={{
id: 'whatever',
emails: [{ email: 'foo' }, { email: 'bar' }],
}}
>
<ArrayInput source="emails">
<SimpleFormIterator>
<TextInput source="email" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</SideEffectContextProvider>
</SaveContextProvider>
</ThemeProvider>
);
const inputElements = queryAllByLabelText(
'resources.undefined.fields.email'
);
expect(inputElements).toHaveLength(2);
expect((inputElements[0] as HTMLInputElement).disabled).toBeFalsy();
expect((inputElements[0] as HTMLInputElement).value).toBe('foo');
expect((inputElements[1] as HTMLInputElement).disabled).toBeFalsy();
expect((inputElements[1] as HTMLInputElement).value).toBe('bar');
});

it('should render disabled inputs when disabled is true', () => {
const { queryAllByLabelText } = renderWithRedux(
<ThemeProvider theme={theme}>
<SaveContextProvider value={saveContextValue}>
<SideEffectContextProvider value={sideEffectValue}>
<SimpleForm
record={{
id: 'whatever',
emails: [{ email: 'foo' }, { email: 'bar' }],
}}
>
<ArrayInput source="emails" disabled>
<SimpleFormIterator>
<TextInput source="email" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</SideEffectContextProvider>
</SaveContextProvider>
</ThemeProvider>
);
const inputElements = queryAllByLabelText(
'resources.undefined.fields.email'
);
expect(inputElements).toHaveLength(2);
expect((inputElements[0] as HTMLInputElement).disabled).toBeTruthy();
expect((inputElements[0] as HTMLInputElement).value).toBe('foo');
expect((inputElements[1] as HTMLInputElement).disabled).toBeTruthy();
expect((inputElements[1] as HTMLInputElement).value).toBe('bar');
});

it('should display an add item button at least', () => {
const { getByText } = renderWithRedux(
<SaveContextProvider value={saveContextValue}>
Expand Down Expand Up @@ -65,6 +128,24 @@ describe('<SimpleFormIterator />', () => {
expect(queryAllByText('ra.action.add').length).toBe(0);
});

it('should not display add button if disabled is truthy', () => {
const { queryAllByText } = renderWithRedux(
<SaveContextProvider value={saveContextValue}>
<SideEffectContextProvider value={sideEffectValue}>
<SimpleForm>
<ArrayInput source="emails" disabled>
<SimpleFormIterator>
<TextInput source="email" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</SideEffectContextProvider>
</SaveContextProvider>
);

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

it('should not display remove button if disableRemove is truthy', () => {
const { queryAllByText } = renderWithRedux(
<ThemeProvider theme={theme}>
Expand All @@ -90,6 +171,31 @@ describe('<SimpleFormIterator />', () => {
expect(queryAllByText('ra.action.remove').length).toBe(0);
});

it('should not display remove button if disabled is truthy', () => {
const { queryAllByText } = renderWithRedux(
<ThemeProvider theme={theme}>
<SaveContextProvider value={saveContextValue}>
<SideEffectContextProvider value={sideEffectValue}>
<SimpleForm
record={{
id: 'whatever',
emails: [{ email: '' }, { email: '' }],
}}
>
<ArrayInput source="emails" disabled>
<SimpleFormIterator>
<TextInput source="email" />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</SideEffectContextProvider>
</SaveContextProvider>
</ThemeProvider>
);

expect(queryAllByText('ra.action.remove').length).toBe(0);
});

it('should add children row on add button click', async () => {
const {
getByText,
Expand Down
40 changes: 22 additions & 18 deletions packages/ra-ui-materialui/src/form/SimpleFormIterator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const SimpleFormIterator: FC<SimpleFormIteratorProps> = props => {
record,
resource,
source,
disabled,
disableAdd,
disableRemove,
variant,
Expand Down Expand Up @@ -220,6 +221,7 @@ const SimpleFormIterator: FC<SimpleFormIteratorProps> = props => {
? `resources.${resource}.fields.${input.props.source}`
: undefined
: input.props.label,
disabled,
})}
record={
(records &&
Expand All @@ -233,28 +235,29 @@ const SimpleFormIterator: FC<SimpleFormIteratorProps> = props => {
) : null
)}
</section>
{!disableRemoveField(
(records && records[index]) || {},
disableRemove
) && (
<span className={classes.action}>
{cloneElement(removeButton, {
onClick: handleRemoveButtonClick(
removeButton.props.onClick,
index
),
className: classNames(
'button-remove',
`button-remove-${source}-${index}`
),
})}
</span>
)}
{!disabled &&
!disableRemoveField(
(records && records[index]) || {},
disableRemove
) && (
<span className={classes.action}>
{cloneElement(removeButton, {
onClick: handleRemoveButtonClick(
removeButton.props.onClick,
index
),
className: classNames(
'button-remove',
`button-remove-${source}-${index}`
),
})}
</span>
)}
</li>
</CSSTransition>
))}
</TransitionGroup>
{!disableAdd && (
{!disabled && !disableAdd && (
<li className={classes.line}>
<span className={classes.action}>
{cloneElement(addButton, {
Expand Down Expand Up @@ -307,6 +310,7 @@ export interface SimpleFormIteratorProps
basePath?: string;
className?: string;
defaultValue?: any;
disabled?: boolean;
disableAdd?: boolean;
disableRemove?: boolean | DisableRemoveFunction;
margin?: 'none' | 'normal' | 'dense';
Expand Down
3 changes: 3 additions & 0 deletions packages/ra-ui-materialui/src/input/ArrayInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const ArrayInput: FC<ArrayInputProps> = ({
source,
validate,
variant,
disabled,
margin = 'dense',
...rest
}) => {
Expand Down Expand Up @@ -93,6 +94,7 @@ const ArrayInput: FC<ArrayInputProps> = ({
source,
variant,
margin,
disabled,
})}
</FormControl>
);
Expand Down Expand Up @@ -122,5 +124,6 @@ ArrayInput.defaultProps = {

export interface ArrayInputProps extends InputProps {
children: ReactElement;
disabled?: boolean;
}
export default ArrayInput;

0 comments on commit 1ef2add

Please sign in to comment.