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

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>