Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c203bcb
feat(autocomplete): exclude name in input and add getHiddenInputProps
wingkwong Jun 30, 2024
36c38df
Merge branch 'canary' into fix/eng-1067
wingkwong Jul 4, 2024
049c1bd
fix(autocomplete): revise getInputProps logic
wingkwong Jul 4, 2024
cde7cad
feat(autocomplete): hidden input
wingkwong Jul 4, 2024
db33506
feat(autocomplete): include HiddenInput in autocomplete
wingkwong Jul 4, 2024
4f44322
feat(changeset): add changeset
wingkwong Jul 4, 2024
4144d44
fix(autocomplete): set empty string by default for value
wingkwong Jul 5, 2024
e95d528
fix(autocomplete): avoid passing custom attribute to DOM
wingkwong Jul 5, 2024
e137507
fix(autocomplete): props comments
wingkwong Jul 5, 2024
e8c4149
feat(autocomplete): include @react-aria/form
wingkwong Jul 5, 2024
64599e7
feat(autocomplete): add inputData map for hidden input
wingkwong Jul 5, 2024
91f4c5a
feat(autocomplete): useHiddenInput
wingkwong Jul 5, 2024
455f985
chore(deps): pnpm-lock.yaml
wingkwong Jul 5, 2024
f29fc26
Merge branch 'canary' into fix/eng-1067
wingkwong Sep 19, 2024
018cb53
fix(autocomplete): add missing import
wingkwong Sep 19, 2024
e02d9c7
feat(autocomplete): add WithFormTemplate
wingkwong Sep 19, 2024
c8b45a8
Merge branch 'canary' into fix/eng-1067
wingkwong Sep 29, 2024
3fb677e
Merge branch 'canary' into fix/eng-1067
wingkwong Oct 3, 2024
caa14e8
fix(autocomplete): include onSelectionChange logic and add missing on…
wingkwong Oct 3, 2024
737ad50
chore(autocomplete): remove duplicate dependency
wingkwong Oct 3, 2024
ae5940c
refactor(autocomplete): remove props
wingkwong Oct 4, 2024
313119d
Merge branch 'canary' into fix/eng-1067
wingkwong Oct 4, 2024
fe8dc2f
feat(autocomplete): include hiddenInputRef
wingkwong Oct 4, 2024
853e3dd
feat(autocomplete): include hiddenInputRef logic
wingkwong Oct 4, 2024
ea8894a
feat(autocomplete): add test case
wingkwong Oct 4, 2024
a0a7042
fix(autocomplete): typing on onSelectionChange
wingkwong Oct 4, 2024
f8cce31
fix(autocomplete): handle allowsCustomValue
wingkwong Oct 6, 2024
1a84b7b
chore(autocomplete): add default values
wingkwong Oct 6, 2024
8ee75de
fix(autocomplete): pr comments
wingkwong Oct 6, 2024
5eaf174
refactor(autocomplete): add hiddenInputRef.current check
wingkwong Oct 6, 2024
4407700
Merge branch 'beta/release-next' into fix/eng-1067
wingkwong Nov 8, 2024
0f71b97
Update .changeset/purple-pillows-beg.md
jrgarciadev Nov 15, 2024
09bcf2b
Merge branch 'beta/release-next' into fix/eng-1067
wingkwong Nov 18, 2024
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/purple-pillows-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/autocomplete": patch
---

return autocomplete value instead of label in form submission (#3353, #3343)
26 changes: 26 additions & 0 deletions packages/components/autocomplete/__tests__/autocomplete.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,7 @@ describe("Autocomplete with React Hook Form", () => {
let submitButton: HTMLButtonElement;
let wrapper: any;
let onSubmit: () => void;
let getReactHookFormValues: (key: string) => any;

beforeEach(() => {
const {result} = renderHook(() =>
Expand All @@ -745,10 +746,13 @@ describe("Autocomplete with React Hook Form", () => {
handleSubmit,
register,
formState: {errors},
getValues,
} = result.current;

onSubmit = jest.fn();

getReactHookFormValues = getValues;

wrapper = render(
<form className="flex w-full max-w-xs flex-col gap-2" onSubmit={handleSubmit(onSubmit)}>
<Autocomplete
Expand Down Expand Up @@ -822,4 +826,26 @@ describe("Autocomplete with React Hook Form", () => {

expect(onSubmit).toHaveBeenCalledTimes(1);
});

it("should have correct form values", async () => {
const user = userEvent.setup();

await user.click(autocomplete3);

expect(autocomplete3).toHaveAttribute("aria-expanded", "true");

let listboxItems = wrapper.getAllByRole("option");

await user.click(listboxItems[1]);

expect(autocomplete3).toHaveValue("Dog");

await user.click(submitButton);

expect(onSubmit).toHaveBeenCalledTimes(1);

expect(getReactHookFormValues("withDefaultValue")).toEqual("cat");
expect(getReactHookFormValues("withoutDefaultValue")).toEqual("");
expect(getReactHookFormValues("requiredField")).toEqual("dog");
});
});
1 change: 1 addition & 0 deletions packages/components/autocomplete/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@nextui-org/use-safe-layout-effect": "workspace:*",
"@react-aria/combobox": "3.10.3",
"@react-aria/focus": "3.18.2",
"@react-aria/form": "3.0.5",
"@react-aria/i18n": "3.12.2",
"@react-aria/interactions": "3.22.2",
"@react-aria/utils": "3.25.2",
Expand Down
3 changes: 3 additions & 0 deletions packages/components/autocomplete/src/autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {ForwardedRef, ReactElement, Ref} from "react";
import {AnimatePresence} from "framer-motion";

import {UseAutocompleteProps, useAutocomplete} from "./use-autocomplete";
import {HiddenInput} from "./hidden-input";

interface Props<T> extends UseAutocompleteProps<T> {}

Expand All @@ -29,6 +30,7 @@ function Autocomplete<T extends object>(props: Props<T>, ref: ForwardedRef<HTMLI
getClearButtonProps,
getListBoxWrapperProps,
getEndContentWrapperProps,
getHiddenInputProps,
} = useAutocomplete<T>({...props, ref});

const listboxProps = getListBoxProps();
Expand All @@ -45,6 +47,7 @@ function Autocomplete<T extends object>(props: Props<T>, ref: ForwardedRef<HTMLI

return (
<Component {...getBaseProps()}>
<HiddenInput {...getHiddenInputProps()} />
<Input
{...getInputProps()}
endContent={
Expand Down
85 changes: 85 additions & 0 deletions packages/components/autocomplete/src/hidden-input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import type {ComboBoxState} from "@react-stately/combobox";

import React, {ReactNode, RefObject} from "react";
import {useFormReset} from "@react-aria/utils";
import {useFormValidation} from "@react-aria/form";

import {inputData} from "./use-autocomplete";

export interface AriaHiddenInputProps {
/**
* Describes the type of autocomplete functionality the input should provide if any.
* See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefautocomplete).
*/
autoComplete?: string;
/** The text label for the input. */
label?: ReactNode;
/** HTML form input name. */
name?: string;
/** Sets the disabled state of the input. */
isDisabled?: boolean;
/** Whether the input is required. */
isRequired?: boolean;
}

type NativeHTMLInputProps = Omit<
React.InputHTMLAttributes<HTMLInputElement>,
keyof AriaHiddenInputProps
>;

type CombinedAriaInputProps = NativeHTMLInputProps & AriaHiddenInputProps;

export interface HiddenInputProps<T> extends CombinedAriaInputProps {
/** State for the input. */
state: ComboBoxState<T>;
/** A ref to the hidden `<input>` element. */
hiddenInputRef?: RefObject<HTMLInputElement>;
/** A ref to the `<input>` element. */
inputRef?: RefObject<HTMLInputElement>;
}

export function useHiddenInput<T>(props: HiddenInputProps<T>) {
const data = inputData.get(props.state) || {};

const {
state,
autoComplete,
name = data.name,
isDisabled = data.isDisabled,
hiddenInputRef,
inputRef,
onChange,
} = props;

const {validationBehavior, isRequired} = data;

Comment thread
wingkwong marked this conversation as resolved.
useFormReset(inputRef!, state.selectedKey, state.setSelectedKey);
useFormValidation(
{
validationBehavior,
focus: () => inputRef?.current?.focus(),
},
state,
inputRef,
);

return {
name,
ref: hiddenInputRef,
type: "hidden",
disabled: isDisabled,
required: isRequired,
autoComplete,
value: state.selectedKey ?? inputRef?.current?.value ?? "",
onChange: (e: React.ChangeEvent<HTMLInputElement>) => {
state.setSelectedKey(e.target.value);
onChange?.(e);
},
};
}
Comment thread
wingkwong marked this conversation as resolved.

export function HiddenInput<T>(props: HiddenInputProps<T>) {
const inputProps = useHiddenInput(props);

return <input {...inputProps} />;
}
Loading