Typeahead

A basic, easily extended component for quickly creating elegant typeaheads with any form text input.

Example

Use v-model to bind the input value, and target to point to the ideal input element.

If you want to clear the v-model of typeahead, simply set it to null, the corresponding input value will also be cleared.



<template>
  <section class="uiv">
    <Btn type="primary" @click="model = states[0]">Set to Alabama</Btn>
    <Btn @click="model = null">Clear</Btn>
    <hr />
    <label for="input">States of America:</label>
    <input
      id="input"
      class="form-control"
      type="text"
      placeholder="Type to search..."
    />
    <Typeahead v-model="model" target="#input" :data="states" item-key="name" />
    <br />
    <Alert v-show="model">You selected {{ model }}</Alert>
  </section>
</template>

<script setup>
import { ref } from 'vue';
import { Alert, Typeahead, Btn } from 'uiv';
import { data as states } from './states.json';

const model = ref('');
</script>

Target

A target can be:

  • Selector that can be recognized by querySelect.
  • Reference to Element.
  • Reference to Component.

TIP

If you use a component reference, the corresponding component's root element must be an input element.

An example using element reference target:


<template>
  <section class="uiv">
    <label>States of America:</label>
    <input
      ref="input"
      class="form-control"
      type="text"
      placeholder="Type to search..."
    />
    <Typeahead v-model="model" :target="input" :data="states" item-key="name" />
    <br />
    <Alert v-show="model">You selected {{ model }}</Alert>
  </section>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import { Alert, Typeahead } from 'uiv';
import { data as states } from './states.json';

const input = ref(null);
const model = ref('');
</script>

Match start

Match from the head of item.

TIP

Only work in local data query mode.


<template>
  <section class="uiv">
    <label for="input-2">States of America:</label>
    <input
      id="input-2"
      class="form-control"
      type="text"
      placeholder="Type to search..."
    />
    <Typeahead
      v-model="model"
      target="#input-2"
      match-start
      :data="states"
      item-key="name"
    />
    <br />
    <Alert v-show="model">You selected {{ model }}</Alert>
  </section>
</template>

<script setup>
import { ref } from 'vue';
import { Alert, Typeahead } from 'uiv';
import { data as states } from './states.json';

const model = ref('');
</script>

Force select

Force user to select from the options or the model will be empty.


<template>
  <section class="uiv">
    <label for="input-3">States of America:</label>
    <input
      id="input-3"
      class="form-control"
      type="text"
      placeholder="Type to search..."
    />
    <Typeahead
      v-model="model"
      target="#input-3"
      force-select
      :data="states"
      item-key="name"
    />
    <br />
    <Alert v-show="model">You selected {{ model }}</Alert>
  </section>
</template>

<script setup>
import { ref } from 'vue';
import { Alert, Typeahead } from 'uiv';
import { data as states } from './states.json';

const model = ref('');
</script>

Async query

You can simply use async-src to perform an AJAX query with built-in query function, or async-function for a custom one if you need more than that.

TIP

ignore-case and match-start won't work in async query mode.

An example using async-src:


<template>
  <section class="uiv">
    <label for="input-4">Users of Github:</label>
    <input
      id="input-4"
      class="form-control"
      type="text"
      placeholder="Type to search..."
    />
    <Typeahead
      v-model="model"
      target="#input-4"
      async-src="https://api.github.com/search/users?q="
      async-key="items"
      item-key="login"
    />
    <br />
    <Alert v-show="model">You selected {{ model }}</Alert>
  </section>
</template>

<script setup>
import { ref } from 'vue';
import { Alert, Typeahead } from 'uiv';

const model = ref('');
</script>

Custom template

Use the item scoped slot to override the typeahead item's template.

  • Use scope="props".
  • The items list will be props.items.
  • The current active item index will be props.activeIndex.
  • Use props.select(item) to select item.
  • (Optional) Use props.highlight(item) to highlight search keywords in item.

An example with custom template and async-function:


<template>
  <section class="uiv">
    <label for="input-5">Users of Github:</label>
    <input
      id="input-5"
      class="form-control"
      type="text"
      placeholder="Type to search..."
    />
    <Typeahead
      v-model="model"
      target="#input-5"
      :async-function="queryFunction"
      item-key="login"
    >
      <template #item="props">
        <li
          v-for="(item, index) in props.items"
          :key="index"
          :class="{ active: props.activeIndex === index }"
        >
          <a role="button" @click="props.select(item)">
            <img width="22px" height="22px" :src="item.avatar_url + '&s=40'" />
            <span v-html="props.highlight(item)"></span>
          </a>
        </li>
      </template>
    </Typeahead>
    <br />
    <Alert v-show="model">You selected {{ model }}</Alert>
  </section>
</template>

<script setup>
import { ref } from 'vue';
import { Alert, Typeahead } from 'uiv';
import axios from 'axios'; // https://github.com/axios/axios

const model = ref('');

function queryFunction(query, done) {
  axios
    .get('https://api.github.com/search/users?q=' + query)
    .then((res) => {
      done(res.data.items);
    })
    .catch((err) => {
      // any error handler
    });
}
</script>

API Reference

Typeahead

Props

NameTypeDefaultRequiredDescription
v-modelThe input or selected value.
targetThe input element to bind with. Can be a select or reference to Element / Component.
dataArrayThe local auto-complete query data.
item-keyStringValue of each data[key] to show, leave blank to use the data object.
append-to-bodyBooleanfalseAppend the typeahead dropdown to body.
ignore-caseBooleantrueIgnore input case while matching. Only work in local data mode.
match-startBooleanfalseMatch from the head of item. Only work in local data mode.
force-selectBooleanfalseForce user to select from the options or the model will be empty.
force-clearBooleanfalseClear the input if no valid options has selected in force-select mode.
open-on-focusBooleantrueOpen the typeahead dropdown on input focus.
open-on-emptyBooleanfalseOpen the typeahead dropdown to show suggestions even if input is empty.
preselectBooleantrueSelect the first item that matches the query automatically.
limitNumber10Limit the options size.
async-srcStringThe ajax url to fetch data using GET method, query string will be append to the end of this prop value, should return JSON object or array.
async-keyStringThe async JSON key to render, leave blank to use the original json object (should be Array).
async-functionFunctionThe custom async query function with 2 params: query as the user input, and done as the callback function with array data (note that async-key won't work with this). See the example in Custom Template section for details.
debounceNumber200Debounce the input for specify milliseconds while in async mode.

Slots

NameDescription
itemUse this scoped slot to override the typeahead item's template.
emptySlot content will be displayed while no results matched (if the slot exist).

Events

NameDescription
loadingAsync loading.
loadedAsync load complete.
loaded-errorAsync load complete with error.
inputItem selected
selected-item-changed(since 1.4.0) On selected item changed, but not confirmed yet, i.e. using keyboard navigation