Skip to content

Commit

Permalink
feat(prompt): disable ok button with validate function (#47)
Browse files Browse the repository at this point in the history
* feat(prompt): disable ok button with validate function

* docs(prompt): add description for validate option
  • Loading branch information
SevenOutman committed Mar 23, 2022
1 parent af69b77 commit a575c6b
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 3 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ prompt(
interface PromptModalProps {
okButtonText?: string;
cancelButtonText?: string;
valdiate?: (inputValue: string) => void;
onOk?: ((inputVal?: string) => void) | ((inputVal: string) => Promise<any>);
onCancel?: (isSubmitLoading?: boolean) => any;
canCancelOnLoading?: boolean;
Expand All @@ -117,12 +118,13 @@ interface PromptModalProps {

- `okButtonText`: Customize "OK" button text.
- `cancelButtonText`: Customize "Cancel" button text.
- `validate`: Validate current input value. Disable OK button if validation fails.
- `onOk`: Callback function when "OK" is clicked, receiving a string representing the user input. If `onOk` returns a `Promise`, "OK" button shows loading status until the promise finishes.
- `onCancel`: Callback function when "Cancel" is clicked. If not provided, "Cancel" is disabled when "OK" is loading.
- `canCancelOnLoading`: When `onCancel` is set, you can still use this option to force disable "Cancel" button.
- `inputProps`: custom input properties, learn more information about `InputProps` from [here](https://rsuitejs.com/components/input#code-lt-input-gt-code)

## Testability
## Testing

If you use `@rsuite/interactions` to call alert dialogs in your app, you can easily test it with `@testing-library/react`.

Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface ConfirmModalProps {
interface PromptModalProps {
okButtonText?: string;
cancelButtonText?: string;
validate?: (inputValue: string) => boolean;
onOk?: ((inputVal?: string) => void) | ((inputVal: string) => Promise<any>);
onCancel?: (isSubmitLoading?: boolean) => any;
canCancelOnLoading?: boolean;
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module.exports = {
setupFilesAfterEnv: ['./jest.setup.js'],
watchPathIgnorePatterns: ['node_modules'],
};
8 changes: 7 additions & 1 deletion src/InteractionModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Button, Modal } from 'rsuite';

function InteractionModal({
okButtonText = '确定',
okButtonDisabled = false,
onOk,
showCancelButton = true,
cancelButtonText = '取消',
Expand Down Expand Up @@ -97,7 +98,12 @@ function InteractionModal({
{cancelButtonText}
</Button>
)}
<Button loading={submitLoading} onClick={handleOk} appearance="primary">
<Button
loading={submitLoading}
disabled={okButtonDisabled}
onClick={handleOk}
appearance="primary"
>
{okButtonText}
</Button>
</Modal.Footer>
Expand Down
12 changes: 12 additions & 0 deletions src/__tests__/InteractionModal.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ it('renders custom button text', () => {
expect(getByRole('button', { name: okButtonText })).toBeInTheDocument();
});

it('disables ok button when okButtonDisabled=true', () => {
const { getByRole } = render(
<InteractionModal okButtonDisabled>Hey</InteractionModal>
);

expect(
within(getByRole('alertdialog')).getByRole('button', {
name: '确定',
})
).toBeDisabled();
});

it('hides dialog on clicking ok button', async () => {
const { getByRole } = render(<InteractionModal></InteractionModal>);

Expand Down
18 changes: 18 additions & 0 deletions src/__tests__/prompt.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ it('renders custom button text', async () => {
).toBeInTheDocument();
});

it('disable OK button if validation fails', () => {
prompt('Message', '', {
validate: () => false,
});

expect(screen.getByRole('button', { name: '确定' })).toBeDisabled();
});

it('enable OK button when validation passes', () => {
prompt('Message', '', {
validate: (value) => value === 'expected',
});

userEvent.type(screen.getByRole('textbox'), 'expected');

expect(screen.getByRole('button', { name: '确定' })).not.toBeDisabled();
});

describe('resolves correctly', () => {
const inputValue = 'Input value';

Expand Down
7 changes: 6 additions & 1 deletion src/prompt.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ function PromptModal({
message,
defaultResult = '',
onOk,
validate,
inputProps,
style,
...props
Expand All @@ -20,7 +21,11 @@ function PromptModal({
const handleOk = useCallback(() => onOk(result), [onOk, result]);

return (
<InteractionModal {...props} onOk={handleOk}>
<InteractionModal
{...props}
okButtonDisabled={validate?.(result) === false}
onOk={handleOk}
>
<div style={{ padding: '5px' }} className="modal-content">
{message}
<Input
Expand Down

0 comments on commit a575c6b

Please sign in to comment.