Skip to content

Commit

Permalink
Fix input validation and dirty state after re-enabling disabled fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Michel Paiva committed Aug 26, 2024
1 parent 6472e3a commit f75bdba
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 5 deletions.
75 changes: 74 additions & 1 deletion packages/ra-core/src/form/useInput.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { FunctionComponent, ReactElement } from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { useFormContext, useWatch } from 'react-hook-form';
import { useForm, useFormContext, useWatch } from 'react-hook-form';
import { CoreAdminContext, SourceContextProvider } from '../core';
import { testDataProvider } from '../dataProvider';
import { Form } from './Form';
Expand Down Expand Up @@ -566,5 +566,78 @@ describe('useInput', () => {
);
});
});

it('should validate and be dirty for inputs that were disabled and re-enabled', async () => {
const InputWithToggle = () => {
const form = useForm({ mode: 'all' });
const [disabled, setDisabled] = React.useState(false);
const { field, fieldState } = useInput({
source: 'title',
resource: 'posts',
validate: required(),
disabled: disabled,
control: form.control,
});

return (
<div>
<button
type="button"
onClick={() => setDisabled(disabled => !disabled)}
>
Toggle
</button>
<input
type="text"
{...field}
data-testid="title-input"
/>
<p>Dirty {fieldState.isDirty ? 'true' : 'false'}</p>
<p>Disabled {field.disabled ? 'true' : 'false'}</p>
<p>Invalid {fieldState.invalid ? 'true' : 'false'}</p>
</div>
);
};

render(
<CoreAdminContext dataProvider={testDataProvider()}>
<Form>
<InputWithToggle />
</Form>
</CoreAdminContext>
);

// start enabled
expect(screen.getByText('Dirty false')).not.toBeNull();
expect(screen.getByText('Disabled false')).not.toBeNull();

// disable
fireEvent.click(screen.getByText('Toggle'));
expect(screen.getByText('Dirty false')).not.toBeNull();
expect(screen.getByText('Disabled true')).not.toBeNull();

// enable
fireEvent.click(screen.getByText('Toggle'));
expect(screen.getByText('Dirty false')).not.toBeNull();
expect(screen.getByText('Disabled false')).not.toBeNull();

// type
fireEvent.change(screen.getByTestId('title-input'), {
target: { value: 'A title' },
});
await waitFor(() => {
expect(screen.getByText('Dirty true')).not.toBeNull();
expect(screen.getByText('Invalid false')).not.toBeNull();
});

// clear
fireEvent.change(screen.getByTestId('title-input'), {
target: { value: '' },
});
await waitFor(() => {
expect(screen.getByText('Dirty true')).not.toBeNull();
expect(screen.getByText('Invalid true')).not.toBeNull();
});
});
});
});
4 changes: 0 additions & 4 deletions packages/ra-core/src/form/useInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,6 @@ export const useInput = <ValueType = any>(
},
},
...options,
// Workaround for https://github.com/react-hook-form/react-hook-form/issues/10907
// FIXME - remove when fixed
// @ts-ignore - only exists since react-hook-form 7.46.0
disabled: options.disabled || undefined,
});

// Because our forms may receive an asynchronously loaded record for instance,
Expand Down

0 comments on commit f75bdba

Please sign in to comment.