Svelte component example

Validation

By default, the Svelte component validates phone numbers by length (sufficient for most use cases — enable usePreciseValidation for stricter matching), surfacing the result through three callback props: onChangeNumber, onChangeValidity, and onChangeErrorCode.

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, onChangeErrorCode fires with 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>
  import IntlTelInput from "intl-tel-input/svelte";
  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());
  };

  let number = $state("");
  let isValid = $state(false);
  let errorCode = $state(null);
  let showValidation = $state(false);
  let submitted = $state(false);

  const invalidMsg = $derived.by(() => {
    if (!showValidation || isValid) return null;
    return yourCodeToDeriveErrorMessage(number, errorCode);
  });

  const validMsg = $derived.by(() => {
    const showValid = showValidation && isValid && submitted;
    return showValid ? `Full number: ${number}` : null;
  });

  const handleChangeNumber = (newNumber) => {
    submitted = false;
    number = newNumber;
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    showValidation = true;
    submitted = true;
  };
</script>

<form onsubmit={handleSubmit}>
  <label for="phone">Phone number</label>
  <IntlTelInput
    onChangeNumber={handleChangeNumber}
    onChangeValidity={(v) => (isValid = v)}
    onChangeErrorCode={(e) => (errorCode = e)}
    initialCountry="auto"
    separateDialCode={true}
    strictMode={true}
    strictRejectAnimation={true}
    {geoIpLookup}
    loadUtils={() => import("intl-tel-input/utils")}
    inputProps={{
      id: "phone",
      onblur: () => (showValidation = true),
    }}
  />
  <button type="submit">Submit</button>
  {#if invalidMsg}
    <div class="invalid">{invalidMsg}</div>
  {/if}
  {#if validMsg}
    <div class="valid">{validMsg}</div>
  {/if}
</form>