Frameworks
React, Vue, Svelte & more
Every wrapper is a thin layer over the same core, so behaviour is identical everywhere.
React
import { PhoneInput } from '@devix-labs/phone-input/react';
import '@devix-labs/phone-input/styles.css';
export function Contact() {
const [phone, setPhone] = useState('');
return (
<PhoneInput
id="phone"
name="phone"
value={phone}
onChange={(e164, result) => setPhone(e164 ?? '')}
preferredCountries={['ae', 'sa']}
/>
);
}
The widget owns the text in the input, so fast typing inside react-hook-form or Formik can't cause a
render loop. value is the E.164 number and is applied only when it differs from the field.
react-hook-form
<Controller
name="phone"
control={control}
rules={{ validate: (_, form) => phoneRef.current?.isValid() || 'Enter a valid number' }}
render={({ field }) => <PhoneInput ref={phoneRef} value={field.value} onChange={(e164) => field.onChange(e164 ?? '')} />}
/>
Vue 3
<script setup>
import { ref } from 'vue';
import PhoneInput from '@devix-labs/phone-input/vue';
import '@devix-labs/phone-input/styles.css';
const phone = ref('');
</script>
<template>
<PhoneInput v-model="phone" :options="{ preferredCountries: ['pk'] }" @validate="valid = $event" />
</template>
Svelte
<script>
import { phoneInput } from '@devix-labs/phone-input/svelte';
let phone = '';
</script>
<input use:phoneInput={{ initialCountry: 'ae', onChange: (r) => (phone = r.e164) }} />
Web component
A form-associated custom element: it submits the E.164 number and takes part in form validation.
<script type="module" src="https://www.devix.pk/cdn/oss/phone-input@1.2.0/element.js"></script>
<link rel="stylesheet" href="https://www.devix.pk/cdn/oss/phone-input@1.2.0/phone-input.min.css">
<form>
<dx-phone-input name="mobile" country="pk" preferred="pk,ae" required></dx-phone-input>
<button>Send</button>
</form>
jQuery
import '@devix-labs/phone-input/jquery'; // or the all-in-one CDN script
$('#phone').phoneInput({ initialCountry: 'gb' });
$('#phone').phoneInput('getNumber'); // "+447400123456"
Updated 15 Sep 2026