Skip to content

Commit

Permalink
Fix form descriptors (GH-74)
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtyomVancyan authored Feb 19, 2024
2 parents cbce126 + 40e5876 commit 09869f8
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 15 deletions.
2 changes: 1 addition & 1 deletion examples/antd5.x/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
"last 1 safari version"
]
}
}
}
19 changes: 18 additions & 1 deletion examples/antd5.x/src/Demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ 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";

import "antd/dist/reset.css";

const Demo = () => {
const [form] = useForm();
const [value, setValue] = useState(null);
const [algorithm, setAlgorithm] = useState("defaultAlgorithm");

Expand All @@ -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 (
Expand All @@ -44,11 +59,13 @@ const Demo = () => {
{JSON.stringify(value, null, 2)}
</pre>
)}
<Form onFinish={handleFinish}>
<Form form={form} onFinish={handleFinish}>
<FormItem name="phone" rules={[{validator}]}>
<PhoneInput enableSearch/>
</FormItem>
<div style={{display: "flex", gap: 24}}>
<Button onClick={setFieldObjectValue}>Set Object Value</Button>
<Button onClick={setFieldRawValue}>Set Raw Value</Button>
<Button htmlType="submit">Preview Value</Button>
<Button htmlType="reset">Reset Value</Button>
<Button onClick={changeTheme}>Change Theme</Button>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": [
Expand Down
39 changes: 28 additions & 11 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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<HTMLInputElement>) => {
onKeyDownMaskHandler(event);
Expand Down Expand Up @@ -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;
Expand Down
54 changes: 53 additions & 1 deletion tests/antd.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,65 @@ describe("Checking the basic rendering and functionality", () => {
<FormItem name="phone">
<PhoneInput/>
</FormItem>
<Button data-testid="button" htmlType="submit">Submit</Button>
</Form>);
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 (
<Form data-testid="form" form={form} initialValues={{phone: {countryCode: 1, areaCode: "702"}}}>
<FormItem name="phone">
<PhoneInput/>
</FormItem>
<Button data-testid="submit" htmlType="submit">Submit</Button>
<Button data-testid="set-string" onClick={setFieldRawValue}>Set String Value</Button>
<Button data-testid="set-object" onClick={setFieldObjectValue}>Set Object Value</Button>
</Form>
)
}

render(<FormWrapper/>);
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(<Form data-testid="form" initialValues={{phone: {countryCode: 1, areaCode: "702", phoneNumber: ""}}}>
<FormItem name="phone" rules={[{
Expand Down

0 comments on commit 09869f8

Please sign in to comment.