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 controlled input to reflect changes in controlled value #1292

Merged
merged 7 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/violet-hornets-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aws-amplify/ui-react": patch
---

update StepperField and CheckboxField to update the visual display when a controlled value is changed
13 changes: 9 additions & 4 deletions packages/react/src/primitives/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,15 @@ const CheckboxPrimitive: Primitive<CheckboxProps, 'input'> = (
// controlled way should always override uncontrolled way
const initialChecked = checked !== undefined ? checked : defaultChecked;

const { dataChecked, dataFocus, onBlur, onChange, onFocus } = useCheckbox(
initialChecked,
onChangeProp
);
const { dataChecked, dataFocus, onBlur, onChange, onFocus, setDataChecked } =
useCheckbox(initialChecked, onChangeProp);

React.useEffect(() => {
const isControlled = checked !== undefined;
if (isControlled && checked !== dataChecked) {
setDataChecked(checked);
}
}, [checked, dataChecked, setDataChecked]);

const buttonTestId = useTestId(testId, ComponentClassNames.CheckboxButton);
const iconTestId = useTestId(testId, ComponentClassNames.CheckboxIcon);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,21 @@ describe('Checkbox test suite', () => {
});

describe('Button test suite', () => {
let updateCheckedFunction;
const ControlledCheckbox = () => {
const [checked, setChecked] = React.useState(false);
updateCheckedFunction = setChecked;
return (
<Checkbox
{...basicProps}
onChange={(event) => {
setChecked(event.target.checked);
}}
checked={checked}
/>
);
};

it('should render basic props correctly', async () => {
render(getCheckbox({ ...basicProps }));

Expand All @@ -127,6 +142,23 @@ describe('Checkbox test suite', () => {
expect(button).toHaveAttribute('data-focus', 'false');
expect(button).toHaveClass(ComponentClassNames.CheckboxButton);
});

it('should update the checked button with a change to the controlled value', async () => {
render(<ControlledCheckbox />);

let button = await screen.findByTestId(
`${basicProps.testId}-${ComponentClassNames.CheckboxButton}`
);
expect(button).toHaveAttribute('data-checked', 'false');
expect(button).not.toHaveAttribute('data-disabled');
expect(button).toHaveAttribute('data-focus', 'false');
expect(button).toHaveClass(ComponentClassNames.CheckboxButton);
updateCheckedFunction(true);
button = await screen.findByTestId(
`${basicProps.testId}-${ComponentClassNames.CheckboxButton}`
);
expect(button).toHaveAttribute('data-checked', 'true');
});
});

describe('Icon test suite', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/primitives/Checkbox/useCheckbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ export const useCheckbox = (
setDataFocus(false);
};

return { dataChecked, dataFocus, onBlur, onChange, onFocus };
return { dataChecked, dataFocus, onBlur, onChange, onFocus, setDataChecked };
};
8 changes: 8 additions & 0 deletions packages/react/src/primitives/StepperField/StepperField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,18 @@ const StepperFieldPrimitive: Primitive<StepperFieldProps, 'input'> = (
handleOnBlur,
handleOnChange,
handleOnWheel,
setInputValue,
shouldDisableDecreaseButton,
shouldDisableIncreaseButton,
} = useStepper(props);

React.useEffect(() => {
const isControlled = controlledValue !== undefined;
if (isControlled) {
setInputValue(controlledValue);
}
}, [controlledValue, setInputValue]);

return (
<Flex
className={classNames(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ describe('StepperField: ', () => {

describe('Input field', () => {
const label = 'stepper';
let updateValueFunction;

const ControlledStepper = () => {
const [value, setValue] = React.useState(0);
updateValueFunction = setValue;
return (
<StepperField
label={label}
Expand Down Expand Up @@ -202,6 +204,15 @@ describe('StepperField: ', () => {
expect(onBlur).toHaveBeenCalled();
expect(onWheel).toHaveBeenCalled();
});

it('should update the value correctly(controlled)', async () => {
render(<ControlledStepper />);
let stepperInput = await screen.findByLabelText(label);
expect(stepperInput).toHaveValue(0);
updateValueFunction(8);
stepperInput = await screen.findByLabelText(label);
expect(stepperInput).toHaveValue(8);
});
});

describe('Increase/Decrease button', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/primitives/StepperField/useStepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export const useStepper = ({
handleOnBlur,
handleOnChange,
handleOnWheel,
setInputValue,
shouldDisableDecreaseButton,
shouldDisableIncreaseButton,
};
Expand Down