Skip to content

Commit 09869f8

Browse files
Fix form descriptors (GH-74)
2 parents cbce126 + 40e5876 commit 09869f8

File tree

5 files changed

+101
-15
lines changed

5 files changed

+101
-15
lines changed

examples/antd5.x/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@
3333
"last 1 safari version"
3434
]
3535
}
36-
}
36+
}

examples/antd5.x/src/Demo.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import Form from "antd/es/form";
33
import theme from "antd/es/theme";
44
import Button from "antd/es/button";
55
import Card from "antd/es/card/Card";
6+
import {useForm} from "antd/es/form/Form";
67
import FormItem from "antd/es/form/FormItem";
78
import ConfigProvider from "antd/es/config-provider";
89
import PhoneInput from "antd-phone-input";
910

1011
import "antd/dist/reset.css";
1112

1213
const Demo = () => {
14+
const [form] = useForm();
1315
const [value, setValue] = useState(null);
1416
const [algorithm, setAlgorithm] = useState("defaultAlgorithm");
1517

@@ -28,6 +30,19 @@ const Demo = () => {
2830
}
2931
}
3032

33+
const setFieldObjectValue = () => {
34+
form.setFieldValue("phone", {
35+
"countryCode": 52,
36+
"areaCode": "444",
37+
"phoneNumber": "44444444",
38+
"isoCode": "mx"
39+
});
40+
}
41+
42+
const setFieldRawValue = () => {
43+
form.setFieldValue("phone", "+1 (234) 234 2342");
44+
}
45+
3146
const handleFinish = ({phone}: any) => setValue(phone);
3247

3348
return (
@@ -44,11 +59,13 @@ const Demo = () => {
4459
{JSON.stringify(value, null, 2)}
4560
</pre>
4661
)}
47-
<Form onFinish={handleFinish}>
62+
<Form form={form} onFinish={handleFinish}>
4863
<FormItem name="phone" rules={[{validator}]}>
4964
<PhoneInput enableSearch/>
5065
</FormItem>
5166
<div style={{display: "flex", gap: 24}}>
67+
<Button onClick={setFieldObjectValue}>Set Object Value</Button>
68+
<Button onClick={setFieldRawValue}>Set Raw Value</Button>
5269
<Button htmlType="submit">Preview Value</Button>
5370
<Button htmlType="reset">Reset Value</Button>
5471
<Button onClick={changeTheme}>Change Theme</Button>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "0.3.4",
2+
"version": "0.3.5",
33
"name": "antd-phone-input",
44
"description": "Advanced, highly customizable phone input component for Ant Design.",
55
"keywords": [

src/index.tsx

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
} from "react";
1212
import useFormInstance from "antd/es/form/hooks/useFormInstance";
1313
import {FormContext} from "antd/es/form/context";
14+
import {useWatch} from "antd/es/form/Form";
1415
import Select from "antd/es/select";
1516
import Input from "antd/es/input";
1617

@@ -85,18 +86,22 @@ const PhoneInput = forwardRef(({
8586
return ({...metadata})?.[0] + ({...metadata})?.[2];
8687
}, [countriesList, countryCode, value])
8788

88-
const setFieldValue = useCallback((value: PhoneNumber) => {
89-
if (formInstance) {
90-
let namePath = [];
91-
let formName = (formContext as any)?.name || "";
92-
let fieldName = (antInputProps as any)?.id || "";
93-
if (formName) {
94-
namePath.push(formName);
95-
fieldName = fieldName.slice(formName.length + 1);
96-
}
97-
formInstance.setFieldValue(namePath.concat(fieldName.split("_")), value);
89+
const namePath = useMemo(() => {
90+
let path = [];
91+
let formName = (formContext as any)?.name || "";
92+
let fieldName = (antInputProps as any)?.id || "";
93+
if (formName) {
94+
path.push(formName);
95+
fieldName = fieldName.slice(formName.length + 1);
9896
}
99-
}, [antInputProps, formContext, formInstance])
97+
return path.concat(fieldName.split("_"));
98+
}, [antInputProps, formContext])
99+
100+
const phoneValue = useWatch(namePath, formInstance);
101+
102+
const setFieldValue = useCallback((value: PhoneNumber) => {
103+
if (formInstance) formInstance.setFieldValue(namePath, value);
104+
}, [formInstance, namePath])
100105

101106
const onKeyDown = useCallback((event: KeyboardEvent<HTMLInputElement>) => {
102107
onKeyDownMaskHandler(event);
@@ -129,6 +134,18 @@ const PhoneInput = forwardRef(({
129134
})
130135
}, [forwardedRef])
131136

137+
useEffect(() => {
138+
const rawValue = getRawValue(phoneValue);
139+
const metadata = getMetadata(rawValue);
140+
// Skip if value has not been updated by `setFieldValue`.
141+
if (!metadata?.[3] || rawValue === getRawValue(value)) return;
142+
const formattedNumber = getFormattedNumber(rawValue, metadata?.[3] as string);
143+
const phoneMetadata = parsePhoneNumber(formattedNumber);
144+
setFieldValue({...phoneMetadata, valid: (strict: boolean) => checkValidity(phoneMetadata, strict)});
145+
setCountryCode(metadata?.[0] as string);
146+
setValue(formattedNumber);
147+
}, [phoneValue, value, setFieldValue, setValue])
148+
132149
useEffect(() => {
133150
if (initiatedRef.current) return;
134151
initiatedRef.current = true;

tests/antd.test.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,65 @@ describe("Checking the basic rendering and functionality", () => {
106106
<FormItem name="phone">
107107
<PhoneInput/>
108108
</FormItem>
109-
<Button data-testid="button" htmlType="submit">Submit</Button>
110109
</Form>);
111110
const input = screen.getByDisplayValue("+1 (702)");
112111
await userEvent.type(input, "1234567");
113112
assert(input.getAttribute("value") === "+1 (702) 123 4567");
114113
})
115114

115+
it("Checking field value setters", async () => {
116+
const FormWrapper = () => {
117+
const [form] = Form.useForm();
118+
119+
const setFieldObjectValue = () => {
120+
form.setFieldValue("phone", {
121+
countryCode: 48,
122+
areaCode: "111",
123+
phoneNumber: "1111111",
124+
isoCode: "pl"
125+
});
126+
}
127+
128+
const setFieldRawValue = () => {
129+
form.setFieldValue("phone", "+1 (234) 234 2342");
130+
}
131+
132+
return (
133+
<Form data-testid="form" form={form} initialValues={{phone: {countryCode: 1, areaCode: "702"}}}>
134+
<FormItem name="phone">
135+
<PhoneInput/>
136+
</FormItem>
137+
<Button data-testid="submit" htmlType="submit">Submit</Button>
138+
<Button data-testid="set-string" onClick={setFieldRawValue}>Set String Value</Button>
139+
<Button data-testid="set-object" onClick={setFieldObjectValue}>Set Object Value</Button>
140+
</Form>
141+
)
142+
}
143+
144+
render(<FormWrapper/>);
145+
const form = screen.getByTestId("form");
146+
const submit = screen.getByTestId("submit");
147+
const input = screen.getByDisplayValue("+1 (702)");
148+
const setString = screen.getByTestId("set-string");
149+
const setObject = screen.getByTestId("set-object");
150+
151+
await userEvent.click(setString);
152+
await userEvent.click(submit);
153+
await act(async () => {
154+
await new Promise(r => setTimeout(r, 100));
155+
})
156+
assert(!inputHasError(form)); // valid
157+
assert(input.getAttribute("value") === "+1 (234) 234 2342");
158+
159+
await userEvent.click(setObject);
160+
await userEvent.click(submit);
161+
await act(async () => {
162+
await new Promise(r => setTimeout(r, 100));
163+
})
164+
assert(!inputHasError(form)); // valid
165+
assert(input.getAttribute("value") === "+48 (111) 111 1111");
166+
})
167+
116168
it("Checking validation with casual form actions", async () => {
117169
render(<Form data-testid="form" initialValues={{phone: {countryCode: 1, areaCode: "702", phoneNumber: ""}}}>
118170
<FormItem name="phone" rules={[{

0 commit comments

Comments
 (0)