Vue component example
Validation
By default, the Vue component validates phone numbers by length (sufficient for most use cases — enable usePreciseValidation for stricter matching), surfacing the result through three events: changeNumber, changeValidity, and changeErrorCode.
Validation respects the allowedNumberTypes option, which is set to ["MOBILE", "FIXED_LINE"] by default, meaning it will only consider those types of numbers as valid.
When a number fails validation, changeErrorCode emits the error code, which you can then map to your own custom error message — see Deriving a user-facing error message.
Note: the red/green styling and warning/success icons are not part of the component — in this example they come from Bootstrap form validation.
Demo
Note: by default, validation only considers mobile and fixed line numbers as valid. See
allowedNumberTypes option for more information.
JavaScript
geoIpLookup here uses ipapi's limited free tier — for production, pick a paid plan, another provider, or roll your own.yourCodeToDeriveErrorMessage is up to you — see Deriving a user-facing error message for a worked example.<script setup>
import { computed, ref } from "vue";
import IntlTelInput from "intl-tel-input/vue";
import "intl-tel-input/styles";
const geoIpLookup = (success, failure) => {
fetch("https://ipapi.co/json")
.then(res => res.json())
.then(data => success(data.country_code))
.catch(() => failure());
};
const number = ref("");
const isValid = ref(false);
const errorCode = ref(null);
const showValidation = ref(false);
const submitted = ref(false);
const invalidMsg = computed(() => {
if (!showValidation.value || isValid.value) return null;
return yourCodeToDeriveErrorMessage(number.value, errorCode.value);
});
const validMsg = computed(() => {
const showValid =
showValidation.value && isValid.value && submitted.value;
return showValid ? `Full number: ${number.value}` : null;
});
const handleChangeNumber = (newNumber) => {
submitted.value = false;
number.value = newNumber;
};
const handleBlur = () => {
showValidation.value = true;
};
const handleSubmit = () => {
showValidation.value = true;
submitted.value = true;
};
</script>
<template>
<form @submit.prevent="handleSubmit">
<label for="phone">Phone number</label>
<IntlTelInput
@changeNumber="handleChangeNumber"
@changeValidity="isValid = $event"
@changeErrorCode="errorCode = $event"
initial-country="auto"
:separate-dial-code="true"
:strict-mode="true"
:strict-reject-animation="true"
:geo-ip-lookup="geoIpLookup"
:load-utils="() => import('intl-tel-input/utils')"
:input-props="{
id: 'phone',
onBlur: handleBlur,
}"
/>
<button type="submit">Submit</button>
<div v-if="invalidMsg" class="invalid">{{ invalidMsg }}</div>
<div v-if="validMsg" class="valid">{{ validMsg }}</div>
</form>
</template>