'Can I create a mask for an antd-country-phone-input?
I am using the antd-country-phone-input in my form for international phone numbers. However this does not have a mask and I want to have a masked input. I have searched for hours for a solution to this, but have not come up with any workable solution. Any ideas how to add a mask to this input? Code
//library
import CountryPhoneInput, {
ConfigProvider,
CountryPhoneInputValue,
} from "antd-country-phone-input";
//returning
<ConfigProvider
locale={en}
areaMapper={(area) => {
return {
...area,
emoji: (
<img
alt="flag"
style={{ width: 18, height: 18, verticalAlign: "sub" }}
src={getFlag(area.short)}
/>
),
};
}}
>
<CountryPhoneInput
id={id}
value={{
code: countryValue.code,
short: countryValue.short,
phone: countryValue.phone,
}}
onChange={(value) => {
if (value.code !== Number(countryValue.code)) {
setCountryValue({
code: value.code,
short: value.short,
phone: value.phone,
});
}
// onChange("+" + value.code!.toString() + phone);
}}
onBlur={() => setValidNumber(isValidPhoneNumber(value))}
style={{ height: "50px" }}
className="phone-height"
autoComplete="none"
placeholder={mask}
></CountryPhoneInput>
</ConfigProvider>
Solution 1:[1]
This is what i put together in the end to come up with a masked input for international phone numbers. It works for most countries phone numbers
const PhoneMaskWidget = (props: any) => {
const {value, onChange, id} = props;
const [countryValue, setCountryValue] = useState<CountryPhoneInputValue>({
short: "US",
code: 1,
phone: "",
});
const [mask, setMask] = useState<string>("(XXX)XXX-XXXX");
const [mounting, setMounting] = useState<boolean>(true);
const [validNumber, setValidNumber] = useState<boolean>(true);
const [countrySwitched, setCountrySwtiched] = useState<boolean>(false);
const stripPhone = (phone: any) => {
let formattedPhone = phone.replace(/[()\-. ]/g, "");
return formattedPhone;
};
const getMask = (mask: any) => {
mask = Array.isArray(mask) ? mask[1].split("#").join("X") : mask.split("#").join("X");
const firstIndex = mask.search(/\d/); // will give you the first digit in the string
let lastIndex = -1;
if (firstIndex > -1) {
for (let i = firstIndex + 1; i < mask.length; i++) {
const element = mask[i];
if (!Number(element)) {
lastIndex = i - 1;
break;
}
}
let remove = "";
if (mask[firstIndex - 1] === "(" && mask[lastIndex + 1] === ")") {
remove = mask.slice(firstIndex - 1, lastIndex + 2);
mask = mask.replace(remove, "");
setMask(mask);
}
}
return mask;
};
const getFlag = (short: string) => {
const data = require(`world_countries_lists/flags/24x24/${short.toLowerCase()}.png`);
// for dumi
if (typeof data === "string") {
return data;
}
// for CRA
return data.default;
};
const maskInput = useCallback(
(phoneValue: string, masking?: string) => {
masking = masking || mask;
let phone = stripPhone(phoneValue);
const phoneLength = stripPhone(masking).length;
if (phone.length > phoneLength) {
phone = phone.substring(0, phoneLength);
setCountryValue({ ...countryValue, phone: phone });
}
let maskedPhone = "";
let brackets = -1;
let dash = -1;
let secondDash = -1;
if (masking.indexOf("(") > -1) {
const open = masking.indexOf("(");
const close = masking.indexOf(")");
brackets = close - (open + 1);
}
if (masking.indexOf("-") > -1) {
dash = masking.indexOf("-");
}
if (masking.lastIndexOf("-") > -1) {
secondDash = masking.lastIndexOf("-");
}
if (brackets > -1) {
if (phone!.length > dash - 2) {
maskedPhone =
"(" +
phone?.substring(0, brackets) +
") " +
phone?.substring(brackets, dash - 2) +
"-" +
phone.substring(6, phone.length);
} else if (phone!.length > brackets && brackets >= 0) {
maskedPhone =
"(" +
phone?.substring(0, brackets) +
") " +
phone.substring(brackets, phone.length);
} else {
maskedPhone = phone;
}
} else {
if (phone.length > secondDash - 1 && secondDash > -1 && secondDash !== dash) {
maskedPhone =
phone.substring(0, dash) +
"-" +
phone.substring(dash, secondDash - 1) +
"-" +
phone.substring(secondDash - 1, phone.length);
} else if (phone.length > dash && dash > -1) {
maskedPhone =
phone.substring(0, dash) + "-" + phone.substring(dash, phone.length);
} else {
maskedPhone = phone;
}
}
return maskedPhone;
},
[mask]
);
const parsePhoneNumber = useCallback(
(value: string) => {
if (!value) return;
let phone = phoneparser.parse(value);
const number = phone?.localized?.stripped || phone.stripped;
const countryShort = phone?.country?.iso3166?.alpha2;
if (!countryShort) {
return;
}
const country = countries.find((c: any) => c.iso === countryShort);
const mask = getMask(country.mask);
setMask(mask);
if (countryShort && number && country.code) {
setCountryValue({
short: countryShort,
code: country.code,
phone: maskInput(number.slice(-stripPhone(mask).length), mask),
});
}
},
[maskInput]
);
useEffect(() => {
if (!countryValue) return;
if (!mounting) {
const country = countries.find((c: any) => c.iso === countryValue.short);
setMask(getMask(country.mask));
setCountryValue({
...countryValue,
phone: countrySwitched ? "" : countryValue.phone,
});
setCountrySwtiched(false);
}
if (mounting) {
if (value) parsePhoneNumber(value);
setMounting(false);
}
}, [countryValue.short, countrySwitched, mounting, value, parsePhoneNumber]);
return (
<ConfigProvider
locale={en}
areaMapper={(area) => {
return {
...area,
emoji: (
<img
alt="flag"
style={{ width: 18, height: 18, verticalAlign: "sub" }}
src={getFlag(area.short)}
/>
),
};
}}
>
<CountryPhoneInput
id={id}
value={{
code: countryValue.code,
short: countryValue.short,
phone: !value || value === "" ? "" : countryValue.phone,
}}
onChange={(value) => {
if (value.short !== countryValue.short) {
setCountrySwtiched(true);
}
const maskedPhone = maskInput(value.phone ? value.phone : "");
setCountryValue({
code: value.code,
short: value.short,
phone: maskedPhone,
});
onChange("+" + value.code!.toString() + " " + maskedPhone);
// onChange("+" + value.code!.toString() + stripPhone(maskedPhone));
}}
onBlur={() => {
const maskedPhone = maskInput(countryValue.phone!);
setValidNumber(
isValidPhoneNumber("+ " + countryValue.code + stripPhone(maskedPhone))
);
}}
style={{ height: "50px" }}
className="phone-height"
autoComplete="none"
placeholder={mask}
></CountryPhoneInput>
</ConfigProvider>
);
};
export default PhoneMaskWidget;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | L. Wolf |