Skip to content

🧩 Slots

<VueTelNumInput> exposes slots to customize the prefix button, the input, the search bar, and list rows.

Important:

  • All slots are plain slots (not scoped) in the current implementation.
  • Use your app state (e.g., v-model object) or global CSS if you need data inside slots.
  • If you replace the internal <input> or search <input>, you must keep the model and events in sync.

Prefix button (prefix:*)

These slots render inside the prefix button (country selector trigger) at the left of the input.

Slot namePurposeNotes
prefix:beforeContent before everything in the buttonPlain slot
prefix:flagCustom flag elementPlain slot
prefix:codeCustom dialing code text (+421)Plain slot
prefix:countryNameCustom country labelPlain slot
prefix:chevronCustom chevron / indicatorPlain slot; not rendered if list.hidden is true
prefix:afterContent after everything in the buttonPlain slot

Example:

vue
<VueTelNumInput v-model="model">
  <template #prefix:flag>
    <img :src="`/flags/${model.iso}.svg`" alt="" width="16" height="12" />
  </template>

  <template #prefix:code>
    <span class="muted">{{ model.code }}</span>
  </template>

  <template #prefix:chevron>
    <svg width="12" height="12" viewBox="0 0 16 16"><path d="..." /></svg>
  </template>
</VueTelNumInput>

Input (input)

Replace the entire input field.

Slot namePurposeNotes
inputReplace the internal <input>You must: (1) sync v-model yourself, (2) forward focus and blur if needed

Minimal example (manual sync):

vue
<VueTelNumInput v-model="model">
  <template #input>
    <input
      :value="model.value"
      @input="e => model.value = { ...model.value, value: (e.target as HTMLInputElement).value }"
      @focus="$emit('focus')"
      @blur="$emit('blur')"
      :placeholder="`Number for ${model.name} (${model.code})`"
    />
  </template>
</VueTelNumInput>

Search area

You can replace the whole search row or just parts of it.

Slot namePurposeNotes
body:searchReplace the entire search container rowWraps icon + input + before/after; plain slot
search:beforeContent before the search icon/inputPlain slot
search:iconReplace the search iconPlain slot
search:inputReplace the search <input>Plain slot; you must bind to model.search yourself
search:afterContent after the search inputPlain slot

Example (custom icon + input):

vue
<VueTelNumInput v-model="model">
  <template #search:icon>
    <span style="margin-left:12px">🔎</span>
  </template>

  <template #search:input>
    <input
      v-model="model.search"
      placeholder="Type a country or code…"
    />
  </template>
</VueTelNumInput>

Full override:

vue
<VueTelNumInput v-model="model">
  <template #body:search>
    <div class="my-search">
      <input v-model="model.search" placeholder="Find country…" />
      <button @click="model.search = ''">Clear</button>
    </div>
  </template>
</VueTelNumInput>

List rows (item:*)

Slot namePurposeNotes
item:beforeContent before row contentsPlain slot
item:flagReplace the row flagPlain slot
item:codeReplace the row dialing codePlain slot
item:countryNameReplace the row country namePlain slot
item:afterContent after row contentsPlain slot

Example (simple embellishments):

vue
<VueTelNumInput v-model="model">
  <template #item:before>
    <span>•</span>
  </template>

    <template #item:flag>
        <!-- You don't have row data here; keep visuals generic or use CSS -->
        <span class="flag-placeholder" />
    </template>

    <template #item:code>
        <span class="muted">(code)</span>
    </template>
</VueTelNumInput>

Note: The current version does not provide per-row scoped data (like data.iso) to item:* slots. If you need fully custom row rendering with access to each row’s iso/code/name, consider opening a feature request for scoped item slots.

Tips & Caveats

  • If you hide the dropdown via list.hidden = true, prefix:chevron won’t render (as in the component).
  • When replacing the internal <input> or search <input>:
    • Update model.value / model.search yourself.
    • Forward @focus / @blur if you rely on those events.
    • Respect input.maxLength, input.required, etc., if your UI should mimic defaults.
  • For purely visual tweaks, prefer CSS (via component CSS variables) over slots to avoid re-implementing behavior.