Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/7span/vue-list/llms.txt

Use this file to discover all available pages before exploring further.

The <VueListSearch> component provides a search input that automatically triggers data fetching when the user types. It includes built-in debouncing to avoid excessive API calls.

Basic usage

<template>
  <VueList endpoint="users">
    <VueListSearch />
    
    <VueListItems #default="{ items }">
      <div v-for="user in items" :key="user.id">
        {{ user.name }}
      </div>
    </VueListItems>
  </VueList>
</template>

Props

debounceTime
number
default:"1000"
Debounce delay in milliseconds. The search won’t trigger until the user stops typing for this duration.
<VueListSearch :debounce-time="500" />

Slot

The default slot receives a scope object with the search state and setter:
<VueListSearch #default="{ search, setSearch }">
  <input
    type="search"
    :value="search"
    @input="setSearch($event.target.value)"
    placeholder="Search users..."
    class="search-input"
  />
</VueListSearch>

Scope object

  • search - Current search query string
  • setSearch(value) - Function to update the search (already debounced)

Behavior

  • Debounced by default: Waits for the user to stop typing before fetching data
  • Resets to page 1: When search changes, the list automatically goes back to the first page
  • Accessible via requestHandler: The search value is passed to your requestHandler as context.search

Examples

Styled search input

<VueListSearch :debounce-time="300">
  <template #default="{ search, setSearch }">
    <div class="search-container">
      <input
        type="search"
        :value="search"
        @input="setSearch($event.target.value)"
        placeholder="Search..."
        class="px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500"
      />
    </div>
  </template>
</VueListSearch>

With search icon

<VueListSearch>
  <template #default="{ search, setSearch }">
    <div class="relative">
      <svg class="absolute left-3 top-3 w-5 h-5 text-gray-400" fill="none" stroke="currentColor">
        <path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
      </svg>
      <input
        type="search"
        :value="search"
        @input="setSearch($event.target.value)"
        placeholder="Search products..."
        class="pl-10 pr-4 py-2 border rounded"
      />
    </div>
  </template>
</VueListSearch>

With clear button

<VueListSearch>
  <template #default="{ search, setSearch }">
    <div class="search-with-clear">
      <input
        type="search"
        :value="search"
        @input="setSearch($event.target.value)"
        placeholder="Search..."
        class="search-input"
      />
      <button
        v-if="search"
        @click="setSearch('')"
        class="clear-btn"
        type="button"
      >
        ×
      </button>
    </div>
  </template>
</VueListSearch>

With loading indicator

<VueList endpoint="users" #default="{ isLoading }">
  <VueListSearch>
    <template #default="{ search, setSearch }">
      <div class="relative">
        <input
          type="search"
          :value="search"
          @input="setSearch($event.target.value)"
          placeholder="Search users..."
          class="w-full px-4 py-2 border rounded"
        />
        <div v-if="isLoading" class="absolute right-3 top-3">
          <svg class="animate-spin h-5 w-5 text-blue-500" fill="none" viewBox="0 0 24 24">
            <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
            <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
          </svg>
        </div>
      </div>
    </template>
  </VueListSearch>
  
  <!-- ... items -->
</VueList>

Advanced search with filters

<template>
  <VueList endpoint="products" v-model:filters="filters">
    <div class="search-bar">
      <VueListSearch :debounce-time="500">
        <template #default="{ search, setSearch }">
          <input
            type="search"
            :value="search"
            @input="setSearch($event.target.value)"
            placeholder="Search products..."
          />
        </template>
      </VueListSearch>
      
      <select v-model="filters.category">
        <option value="">All categories</option>
        <option value="electronics">Electronics</option>
        <option value="clothing">Clothing</option>
      </select>
      
      <label>
        <input type="checkbox" v-model="filters.inStock" />
        In stock only
      </label>
    </div>
    
    <VueListItems #default="{ items }">
      <!-- render items -->
    </VueListItems>
  </VueList>
</template>

<script setup>
import { ref } from 'vue'

const filters = ref({
  category: '',
  inStock: false
})
</script>

Handling search in requestHandler

The search value is passed to your request handler as context.search:
app.use(VueList, {
  requestHandler(context) {
    const { endpoint, page, perPage, search } = context
    
    return axios.get(`/api/${endpoint}`, {
      params: {
        page,
        limit: perPage,
        q: search, // Pass search to your API
      }
    })
    .then(({ data }) => ({
      items: data.results,
      count: data.total
    }))
  }
})
Adjust debounceTime based on your use case:
  • 300-500ms: Fast, responsive search for local or cached data
  • 1000ms (default): Good balance for most APIs
  • 1500-2000ms: Reduces load for expensive search operations
Searching automatically resets the list to page 1 to show the first page of search results.

Next steps

Filtering and sorting

Combine search with filters and sorting

Request handler

Learn how to handle search in your API