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

update SwitchField to allow updates on controlled component #1302

Merged
merged 6 commits into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/fifty-keys-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aws-amplify/ui-react": patch
---

update SwitchField to allow user updates on controlled component
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
import { SwitchField } from '@aws-amplify/ui-react';
import { SwitchField, Button } from '@aws-amplify/ui-react';
import * as React from 'react';

export const SwitchFieldIsCheckedExample = () => {
return <SwitchField label="This is a switch" isChecked={true} />;
const [isChecked, setIsChecked] = React.useState(true);

return (
<>
<SwitchField
label="This is a switch"
isChecked={isChecked}
onChange={(e) => {
setIsChecked(e.target.checked);
}}
/>
<Button
onClick={() => {
setIsChecked(true);
}}
>
Switch On
</Button>
</>
);
};
6 changes: 4 additions & 2 deletions docs/src/pages/components/switchfield/react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ The most basic usage simply includes a SwitchField component passing in a requir

<Fragment>{() => import('./../shared/formFieldAccessibility.mdx')}</Fragment>

### isChecked
### Controlled component

The `isChecked` property is a `boolean` value that defines if the switch is on or off. This is a boolean property and being set to either true or false will change this into a controlled switchField which can only be switched on or off using this controlled value.
The `SwitchFIeld` can be a controlled component by passing in the controlled boolean value as the `isChecked` prop.
To allow the user to toggle a controlled `SwitchField`, the `onChange` handler must be passed in and update the controlled
value. An example of this pattern is displayed below.

<Example>
<SwitchFieldIsCheckedExample />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,23 @@ describe('Switch Field', () => {
});

describe('Input', () => {
let updateControlledValue;
const ControlledSwitch = () => {
const [isChecked, setIsChecked] = React.useState(true);
const changeFunction = (e) => {
setIsChecked(e.target.checked);
};
updateControlledValue = setIsChecked;

return (
<SwitchField
label={label}
isChecked={isChecked}
onChange={changeFunction}
/>
);
};

it('should create a checkbox input element', async () => {
const { container } = render(<SwitchField label={label} />);

Expand Down Expand Up @@ -128,14 +145,34 @@ describe('Switch Field', () => {
});

it('should set the input to checked with the isChecked prop', async () => {
const { container } = render(
<SwitchField label={label} isChecked={true} />
);
const { container } = render(<ControlledSwitch />);

const field = container.getElementsByTagName('input')[0];
expect(field).toBeChecked();
});

it('should update the checked value when a controlled value is updated', async () => {
render(<ControlledSwitch />);

let input = await screen.findByLabelText(label);
expect(input).toBeChecked();

updateControlledValue(false);
input = await screen.findByLabelText(label);
expect(input).not.toBeChecked();
});

it('should update the checked value with a click event', async () => {
render(<ControlledSwitch />);

let input = await screen.findByLabelText(label);
expect(input).toBeChecked();

userEvent.click(input);
input = await screen.findByLabelText(label);
expect(input).not.toBeChecked();
});

it('should set the input to checked with the defaultChecked prop', async () => {
const { container } = render(
<SwitchField label={label} defaultChecked={true} />
Expand Down
9 changes: 4 additions & 5 deletions packages/react/src/primitives/SwitchField/useSwitch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ export const useSwitch = (props) => {
event.preventDefault();
return;
}
if (!isControlled) {
typeof onChange === 'function' && onChange(event);
setIsOn(event.target.checked);
}

typeof onChange === 'function' && onChange(event);
setIsOn(event.target.checked);
},
[onChange, isControlled, isDisabled]
[onChange, isDisabled]
);

if (isControlled && isOn !== isChecked) {
Expand Down