Migration to v6
Before reading
VPhoneInput has been fully rewritten for v6 to improve its features and provide a new usePhoneInput composable for integrations outside Vuetify. Many API have changed, so you should read every section of this guide. If you have any question, fill free to open an issue on the repository.
This migration guide is mostly using plugin configuration as example of API changes, but you can also apply those changes to the component properties if that's what you are using.
Vue and Vuetify support
VPhoneInput now requires Vue v3.5.0 or up, and Vuetify v3.10.7 or up.
Better TypeScript support
VPhoneInput component's typings have been improved to strictly reflect the available properties, slots, events or exposed values. This may cause legitimate TypeScript errors which were not emitted previously.
CSS styles import
CSS styles import path for VPhoneInput have renamed from v-phone-input/dist/v-phone-input.css to v-phone-input/styles to match Vuetify styles import path.
import 'v-phone-input/dist/v-phone-input.css';
import 'v-phone-input/styles';Country input mode
Previously, VPhoneInput component shipped with default VSelect input for country selection. This behavior created unused code being packaged into production builds when always using enableSearchingCountry property (to display an autocomplete input instead of a select).
To avoid this, enableSearchingCountry property has been removed, and you must now pass either selectPhoneCountryInput or autocompletePhoneCountryInput to the component props or the plugin factory. In addition, it is not necessary to register VAutocomplete anymore when using the autocomplete country input.
import { selectPhoneCountryInput } from 'v-phone-input';
createVPhoneInput({
...selectPhoneCountryInput,
});import { autocompletePhoneCountryInput } from 'v-phone-input';
createVPhoneInput({
// ...
enableSearchingCountry: true,
...autocompletePhoneCountryInput,
});Country display
Country display component have been renamed:
VCountryIconSvgrenamed toVPhoneCountryFlagSvgVCountryIconSpriterenamed toVPhoneCountryFlagSprite
Country display customization property has been renamed to countryDisplayComponent (previously countryIconMode). In order to reduce package's footprint, svg and sprite possible special values have been removed, and must be replaced with new country display component:
import { VPhoneCountryFlagSvg } from 'v-phone-input';
createVPhoneInput({
// ...
countryIconMode: 'svg',
countryDisplayComponent: VPhoneCountryFlagSvg,
});import { VPhoneCountryFlagSprite } from 'v-phone-input';
createVPhoneInput({
// ...
countryIconMode: 'sprite',
countryDisplayComponent: VPhoneCountryFlagSprite,
});createVPhoneInput({
// ...
countryIconMode: MyCustomCountryIconComponent,
countryDisplayComponent: MyCustomCountryIconComponent,
});Country guessing
Country guessing is now done through a function instead of an object. countryGuesser property is now named guessCountry, and guessCountry boolean property has been removed. To disable country guessing (which remains the default behavior), you must now pass a null or undefined value to guessCountry property. In addition, Ip2cCountryGuesser is replaced by guessPhoneCountry.
import { Ip2cCountryGuesser } from 'v-phone-input';
import { guessPhoneCountry } from 'v-phone-input';
createVPhoneInput({
// ...
countryGuesser: new Ip2cCountryGuesser(),
guessCountry: guessPhoneCountry(),
});import { Ip2cCountryGuesser } from 'v-phone-input';
createVPhoneInput({
// ...
countryGuesser: new Ip2cCountryGuesser(),
guessCountry: false,
guessCountry: null,
});Finally, MemoIp2cCountryGuesser and StorageMemoIp2cCountryGuesser have been removed. You can easily create a memoized country guesser using the new memoizeGuessPhoneCountry function. Here are implementation you can use to replace the removed guesser:
import { MemoIp2cCountryGuesser } from 'v-phone-input';
import { guessPhoneCountry, memoizeGuessPhoneCountry } from 'v-phone-input';
let country: string | null = null;
const guessCountry = memoizeGuessPhoneCountry(
guessPhoneCountry,
() => country,
(nextCountry) => {
country = nextCountry;
},
);
createVPhoneInput({
// ...
countryGuesser: new MemoIp2cCountryGuesser(),
guessCountry: guessPhoneCountry(),
});import { StorageMemoIp2cCountryGuesser } from 'v-phone-input';
import { guessPhoneCountry, memoizeGuessPhoneCountry } from 'v-phone-input';
const guessCountry = memoizeGuessPhoneCountry(
guessPhoneCountry,
() => window.localStorage.getItem('v_phone_input_country') || null,
(nextCountry) => window.localStorage.setItem('v_phone_input_country', nextCountry || null),
);
createVPhoneInput({
// ...
countryGuesser: new StorageMemoIp2cCountryGuesser(),
guessCountry: guessPhoneCountry(),
});Phone number formatting behavior
Prior v6, phone formatting would occur every time the phone number was valid, and immediately. This could lead to unindented input formatting while the user is still typing. To mitigate this issue, formatting is now done on (country or phone) input blur.
We do not recommend this, but you can restore the previous behavior by defining displayFormatDelay property to 0.
createVPhoneInput({
// THIS IS NOT RECOMMENDED!
displayFormatDelay: 0,
});Validation
To reduce code complexity, rules property of the VPhoneInput component does not support phone or context additional parameters anymore. This reduces VPhoneInput code complexity for easier maintenance and tinier build size when this niche feature is not used. If you are relying on those parameters, you should:
- Rely on available
countrytwo-way binding to store the country value inside aref, and use it later or to produce an example phone number; - Parse the
phoneyourself from the rule'svalue, for example usingparsePhoneNumberfromawesome-phonenumber.
Here is a complete example to migrate some/all of your parametized rules usage:
<script
lang="ts"
setup
>
import { getExample, parsePhoneNumber } from "awesome-phonenumber";
import { computed, ref } from "vue";
const phone = ref('');
const country = ref('FR');
const label = computed(() => "Phone");
const example = computed(() => getExample(country.value).number?.national ?? '');
const rules = computed(() => [
(value, phone, { country, label, example }) => {
console.log(phone, country, label, example);
},
(value) => {
const phoneObject = parsePhoneNumber(value ?? '', { regionCode: country.value });
// equivalent in v6:
console.log(phone, country, label, example);
},
]);
</script>
<template>
<v-phone-input
v-model="phone"
v-model:country="country"
:label="label"
:rules="rules"
/>
</template>Slots changes
country-input and phone-input could previously be used to provide custom input components to the input. Those two slots are now removed. If you need to fine-tune phone number inputs components, you should now use usePhoneInput composable.
In addition, country-icon slot has been renamed to country-display.
Other slots - direct slots like country-name or passed-down slots like country-input:prepend-icon - remain.
Properties changes
In addition to other changes specified in this guide, multiple properties changed:
exampleis now receiving an object with a country property instead of a country object;disableGuessLoadinghas been replaced byguessLoading, which does the opposite;invalidMessagewithnullwill no longer disable validation, but instead will make the validation rule returnsfalseinstead of a message. If you want to disable validation, usevalidatewithnullinstead.phoneValidatorhas been renamed tovalidate;wrapperPropshas been renamed towrapperAttrs;