Open stoplion opened 3 years ago
Import { useRef } from 'React';
const phoneNoRef = useRef();
return ( <IntlTelInput ref={phoneNoRef} ..... onSelectFlag={() => { const { current } = phoneNoRef; }} />
I'm not sure if you can do what @goelshobhit suggests but I might be wrong. I have checked master
branch for ref
prop on IntlTelInput
. No hits. The TelInput
rendered by the main export of the package (IntlTelInput
) does take a ref
but I see no way of getting to it and if you could, you'd be overwriting what the package itself passes to it.
Here's what I'm doing (using v4.3.4 of react-intl-tel-input
which has the same limitation):
TLDR; useRef
on wrapper element and then on mount, query for input
element and assign to a second ref you use just for storing the input.
const InputPhone = ({ autoFocus, field, onKeyDown, onPhoneNumberChange, onSelectFlag }: InputPhoneProps) => {
// NOTE: all this getting of input el to add a blur event listener to it is to
// remove the error / success message on blur of input (after user re-selects input after submit).
// Submit (enter key down on input or press of button) will auto blur input without removing messages.
// If this is not required, remove this code:
const containerRef: MutableRefObject<null | HTMLDivElement> = useRef(null);
const inputRef: MutableRefObject<null | HTMLInputElement> = useRef(null);
useEffect(() => {
const inputEl = containerRef.current?.getElementsByTagName('input')?.[0];
if (!inputEl) {
throw new Error(`Could not find the phone input element with name ${fieldName}`);
}
inputRef.current = inputEl;
inputRef.current.addEventListener('blur', field.onBlur);
return () => {
if (inputRef.current && field.onBlur) {
inputRef.current.removeEventListener('blur', field.onBlur);
}
};
}, []);
return (
<div ref={containerRef}>
<CPInputPhone
autoFocus={autoFocus}
fieldName={field.name ?? fieldName}
onPhoneNumberChange={onPhoneNumberChange}
onSelectFlag={onSelectFlag}
// Pass onKeyDown to telInputProps because these get passed to <input> element
// rendered by react-intl-tel-input.
// onPhoneNumberChange does not get an event to work with. <input>'s onKeyDown does
// so you can detect enter press:
// NOTE: since react-intl-tel-input overwrites onChange and onBlur, passing them to
// telInputProps is useless. onKeyDown is not overwritten.
// https://github.com/patw0929/react-intl-tel-input/blob/v4.3.4/src/components/TelInput.js#L7-L22
telInputProps={{ onKeyDown }}
/>
</div>
);
};
CPInputPhone
is just a wrapper for IntlTelInput
with some class names.
Also note that if you're planning on adding some event listeners (like above) and you're working with useState
... you're gonna have to wrap that in a useRef
too otherwise you'll never get past the initial value of useState. See: https://stackoverflow.com/a/55265764/990159
const [error, setError] = useState(undefined)
field.onBlur = (e) => {
// error will always be `undefined` here.
if (error !== undefined) {
setError(undefined);
}
}
// Fix:
const [error, setError] = useState(undefined)
const errorRef = useRef(error);
const setErrorRef = (err) => {
// keep new value of error after rerender:
errorRef.current = err;
// trigger rerender if necessary:
setError(err);
};
field.onBlur = (e) => {
if (errorRef.current !== undefined) {
setErrorRef(undefined);
}
}
@stoplion @goelshobhit @justin-calleja yes, there is one.
import React, { useEffect, useRef, useState } from 'react';
import IntlTelInput from 'react-intl-tel-input';
function App() {
const intlTelInputRef = useRef<IntlTelInput | null>(null);
useEffect(() => {
intlTelInputRef.current?.tel?.focus();
}, []);
return (
<div className="App">
<IntlTelInput ref={intlTelInputRef} />
</div>
);
}
The intlTelInputRef
has a property called tel
which returns you the <input>
HTML element. If you're looking for the TelInput
React instance child, then I'm afraid that's not in the API yet.
I'm using this package with react-hook-form Controller and I'm using the ref props like this
<Controller
control={control}
name="phone"
render={({ field }) => {
const { name, value, onChange, onBlur, ref } =
field;
return (
<IntlTelInput
ref={(props) => ref(props?.tel)}
fieldName={name}
telInputProps={{
tabIndex: 1,
}}
placeholder="Phone"
containerClassName="intl-tel-input w-100"
fieldId="phone"
value={value}
/>
);
}}
rules={{
required: "Please enter your phone number",
}}
/>
but when I submit the form with empty value it doesn't focus on the input. any ideas?
Is there a way to get a ref of the input?