diff --git a/examples/antd5.x/package.json b/examples/antd5.x/package.json index dff2968..63d4bdf 100644 --- a/examples/antd5.x/package.json +++ b/examples/antd5.x/package.json @@ -33,4 +33,4 @@ "last 1 safari version" ] } -} \ No newline at end of file +} diff --git a/examples/antd5.x/src/Demo.tsx b/examples/antd5.x/src/Demo.tsx index 7795180..0e528f5 100644 --- a/examples/antd5.x/src/Demo.tsx +++ b/examples/antd5.x/src/Demo.tsx @@ -3,6 +3,7 @@ import Form from "antd/es/form"; import theme from "antd/es/theme"; import Button from "antd/es/button"; import Card from "antd/es/card/Card"; +import {useForm} from "antd/es/form/Form"; import FormItem from "antd/es/form/FormItem"; import ConfigProvider from "antd/es/config-provider"; import PhoneInput from "antd-phone-input"; @@ -10,6 +11,7 @@ import PhoneInput from "antd-phone-input"; import "antd/dist/reset.css"; const Demo = () => { + const [form] = useForm(); const [value, setValue] = useState(null); const [algorithm, setAlgorithm] = useState("defaultAlgorithm"); @@ -28,6 +30,19 @@ const Demo = () => { } } + const setFieldObjectValue = () => { + form.setFieldValue("phone", { + "countryCode": 52, + "areaCode": "444", + "phoneNumber": "44444444", + "isoCode": "mx" + }); + } + + const setFieldRawValue = () => { + form.setFieldValue("phone", "+1 (234) 234 2342"); + } + const handleFinish = ({phone}: any) => setValue(phone); return ( @@ -44,11 +59,13 @@ const Demo = () => { {JSON.stringify(value, null, 2)} )} -
+
+ + diff --git a/package.json b/package.json index bc2018e..495363f 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "0.3.4", + "version": "0.3.5", "name": "antd-phone-input", "description": "Advanced, highly customizable phone input component for Ant Design.", "keywords": [ diff --git a/src/index.tsx b/src/index.tsx index 732ce57..4ceff71 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -11,6 +11,7 @@ import { } from "react"; import useFormInstance from "antd/es/form/hooks/useFormInstance"; import {FormContext} from "antd/es/form/context"; +import {useWatch} from "antd/es/form/Form"; import Select from "antd/es/select"; import Input from "antd/es/input"; @@ -85,18 +86,22 @@ const PhoneInput = forwardRef(({ return ({...metadata})?.[0] + ({...metadata})?.[2]; }, [countriesList, countryCode, value]) - const setFieldValue = useCallback((value: PhoneNumber) => { - if (formInstance) { - let namePath = []; - let formName = (formContext as any)?.name || ""; - let fieldName = (antInputProps as any)?.id || ""; - if (formName) { - namePath.push(formName); - fieldName = fieldName.slice(formName.length + 1); - } - formInstance.setFieldValue(namePath.concat(fieldName.split("_")), value); + const namePath = useMemo(() => { + let path = []; + let formName = (formContext as any)?.name || ""; + let fieldName = (antInputProps as any)?.id || ""; + if (formName) { + path.push(formName); + fieldName = fieldName.slice(formName.length + 1); } - }, [antInputProps, formContext, formInstance]) + return path.concat(fieldName.split("_")); + }, [antInputProps, formContext]) + + const phoneValue = useWatch(namePath, formInstance); + + const setFieldValue = useCallback((value: PhoneNumber) => { + if (formInstance) formInstance.setFieldValue(namePath, value); + }, [formInstance, namePath]) const onKeyDown = useCallback((event: KeyboardEvent) => { onKeyDownMaskHandler(event); @@ -129,6 +134,18 @@ const PhoneInput = forwardRef(({ }) }, [forwardedRef]) + useEffect(() => { + const rawValue = getRawValue(phoneValue); + const metadata = getMetadata(rawValue); + // Skip if value has not been updated by `setFieldValue`. + if (!metadata?.[3] || rawValue === getRawValue(value)) return; + const formattedNumber = getFormattedNumber(rawValue, metadata?.[3] as string); + const phoneMetadata = parsePhoneNumber(formattedNumber); + setFieldValue({...phoneMetadata, valid: (strict: boolean) => checkValidity(phoneMetadata, strict)}); + setCountryCode(metadata?.[0] as string); + setValue(formattedNumber); + }, [phoneValue, value, setFieldValue, setValue]) + useEffect(() => { if (initiatedRef.current) return; initiatedRef.current = true; diff --git a/tests/antd.test.tsx b/tests/antd.test.tsx index cdc584e..236d7d6 100644 --- a/tests/antd.test.tsx +++ b/tests/antd.test.tsx @@ -106,13 +106,65 @@ describe("Checking the basic rendering and functionality", () => { - ); const input = screen.getByDisplayValue("+1 (702)"); await userEvent.type(input, "1234567"); assert(input.getAttribute("value") === "+1 (702) 123 4567"); }) + it("Checking field value setters", async () => { + const FormWrapper = () => { + const [form] = Form.useForm(); + + const setFieldObjectValue = () => { + form.setFieldValue("phone", { + countryCode: 48, + areaCode: "111", + phoneNumber: "1111111", + isoCode: "pl" + }); + } + + const setFieldRawValue = () => { + form.setFieldValue("phone", "+1 (234) 234 2342"); + } + + return ( +
+ + + + + + +
+ ) + } + + render(); + const form = screen.getByTestId("form"); + const submit = screen.getByTestId("submit"); + const input = screen.getByDisplayValue("+1 (702)"); + const setString = screen.getByTestId("set-string"); + const setObject = screen.getByTestId("set-object"); + + await userEvent.click(setString); + await userEvent.click(submit); + await act(async () => { + await new Promise(r => setTimeout(r, 100)); + }) + assert(!inputHasError(form)); // valid + assert(input.getAttribute("value") === "+1 (234) 234 2342"); + + await userEvent.click(setObject); + await userEvent.click(submit); + await act(async () => { + await new Promise(r => setTimeout(r, 100)); + }) + assert(!inputHasError(form)); // valid + assert(input.getAttribute("value") === "+48 (111) 111 1111"); + }) + it("Checking validation with casual form actions", async () => { render(