Vue component

A Vue component for the intl-tel-input library. See a live demo on the Validation example page.

Installation

First, install the package:

npm install @intl-tel-input/vue

Then, add something like this to your code:

<script setup>
  import IntlTelInput from "@intl-tel-input/vue";
  import "intl-tel-input/styles";
</script>

<template>
  <IntlTelInput
    initial-country="us"
    :load-utils="() => import('intl-tel-input/utils')"
  />
</template>

Note

The utils script (~260KB) is loaded separately. The example above passes a dynamic import to loadUtils — modern bundlers split this into its own lazy-loaded chunk, so it doesn’t hit your initial bundle. Alternatively, if IntlTelInput is already lazy-loaded in your app, import from "@intl-tel-input/vue/with-utils" to bundle utils directly.

See Best practices for general advice on validation, E.164 storage, initial country, and localisation.

Props

Any of the initialisation options (like initial-country) can also be passed as a prop.

disabled

Type: boolean
Default: false

Sets the disabled attribute of both the telephone input and the selected country button. Use this instead of inputProps.disabled, as this disables the country button too.

initial-value

Type: string
Default: ""
camelCase: initialValue

The initial value to put in the input. This will get auto-formatted on init (according to the number-display-format initialisation option). Only used during initialisation — for ongoing reactive updates, use v-model instead.

input-props

Type: object
Default: {}
camelCase: inputProps

The props to pass to the input element, e.g. id, class, placeholder, required, onBlur.

Note

The following keys are reserved for the component/core library integration and will be ignored: type, value, disabled, readonly, onInput, oninput. Use the component props (disabled, readonly) and component events (change-number, change-country, etc.) instead.

readonly

Type: boolean
Default: false

Sets the readonly attribute of the telephone input and disables the selected country button. Use this instead of inputProps.readonly, as this disables the country button too.

use-precise-validation

Type: boolean
Default: false
camelCase: usePreciseValidation

By default, the component uses the core library’s isValidNumber method for validation, but if you’d rather use isValidNumberPrecise, set this to true.

v-model

Type: string
Default: undefined

The component supports v-model for two-way binding. When the bound value changes, the input is updated via setNumber (skipped while the input is focused, to avoid disrupting typing). When the user types, the bound value is kept in sync via the update:modelValue event. If you don’t use v-model, the component is uncontrolled — use initial-value for the starting value.

<IntlTelInput v-model="phone" />

Initialisation options

All of the core library’s initialisation options are supported as individual Vue component props using the same option name (in kebab-case, the idiomatic Vue form). There are dozens of options — country selector, formatting, validation, placeholders, localisation, and more — see the full list on the Initialisation options page, or try them interactively in the playground. For example:

<IntlTelInput initial-country="us" />

The camelCase form (e.g. initialCountry) also works if you prefer to match the option name exactly as documented.

Note

If you’re migrating from an older version, the previous :initOptions="{ initialCountry: 'us' }" style is no longer supported — pass each option as its own prop instead.

Note

These props are read once at init — changing them later has no effect. For runtime changes, see Accessing instance methods below (e.g. getInstance().setSelectedCountry("gb")).

Events

change-country

Type: (iso2: string) => void
Default: null
camelCase: changeCountry

Emitted when the selected country changes. The handler receives the new country’s iso2 code (e.g. "gb"), or "" if no country is selected.

change-error-code

Type: (errorCode: ValidationError | null) => void
Default: null
camelCase: changeErrorCode

Emitted when the number validation error changes. The handler receives a ValidationError string, or null if the number is valid. See Show a user-facing error message for how to turn the error code into a message. Requires the utils script to be loaded (see above).

change-number

Type: (number: string) => void
Default: null
camelCase: changeNumber

Emitted when the number changes. The handler receives the new number in standardised E.164 format (e.g. "+447700900123"), or "" if the input is empty. Requires the utils script to be loaded (see above).

change-validity

Type: (isValid: boolean) => void
Default: null
camelCase: changeValidity

Emitted when the number validity changes. The handler receives the new validity boolean. Requires the utils script to be loaded (see above).

close-country-selector

Type: () => void
Default: null
camelCase: closeCountrySelector

Emitted when the country selector closes.

open-country-selector

Type: () => void
Default: null
camelCase: openCountrySelector

Emitted when the country selector opens.

strict-reject

Type: (source: "key" | "paste", rejectedInput: string, reason: "invalid" | "max-length") => void
Default: null
camelCase: strictReject

Emitted when strictMode rejects or modifies input. For most cases, strictRejectAnimation gives you a built-in shake/flash animation without writing any handler code — only reach for strict-reject when you need custom feedback (e.g. a toast that explains why the input was rejected).

The handler receives three arguments describing what was rejected and why:

  • source: either "key" (a keystroke) or "paste" (a clipboard paste).
  • rejectedInput: the raw string that was rejected or stripped — for "key" this is the single character pressed, and for "paste" it’s the full pasted text.
  • reason: either "invalid" (the input contained a disallowed character) or "max-length" (accepting the input would have exceeded the maximum valid length for the selected country).

Here is an example that selects a user-facing message based on these args:

if (reason === "max-length") msg = "Maximum length reached for this country";
else if (source === "paste") msg = "Stripped invalid characters from pasted text";
else msg = `Character not allowed: "${rejectedInput}"`;

Accessing instance methods

You can access all of the core library’s instance methods (setNumber, setSelectedCountry, setPlaceholderNumberType, etc.) by passing a ref into the IntlTelInput component (using the ref prop), and then accessing ref.value.instance, e.g. ref.value?.instance?.setSelectedCountry(...);. See the Set Country demo for a full example. You can also access the input DOM element in a similar way: ref.value?.input.

Accessing static methods

You can access all of the core library’s static methods by importing intlTelInput from the same file as the Vue component, e.g. import { intlTelInput } from "@intl-tel-input/vue" (note the lower case “i” in “intlTelInput”). You can then use this as you would with the core library directly, e.g. intlTelInput.getAllCountries() etc.