Skip to main content
You are viewing Pre-Alpha documentation.
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

createFilter

A composable for filtering arrays of items based on search queries, supporting both primitive values and complex objects with customizable filtering logic.


IntermediateMar 26, 2026

Usage

The createFilter composable provides reactive array filtering with multiple modes for different search behaviors. It works with both primitive values and complex objects, and supports filtering by specific keys.

ts
import { ref, shallowRef } from 'vue'
import { createFilter } from '@vuetify/v0'

const query = shallowRef('doe')
const items = ref([
  { name: 'John Doe', age: 30, city: 'New York' },
  { name: 'Jane Doe', age: 25, city: 'Los Angeles' },
  { name: 'Peter Jones', age: 40, city: 'Chicago' },
])

const filter = createFilter({ keys: ['name'] })
const { items: filtered } = filter.apply(query, items)

console.log(filtered.value)
// [
//   { name: 'John Doe', age: 30, city: 'New York' },
//   { name: 'Jane Doe', age: 25, city: 'Los Angeles' }
// ]

Architecture

createFilter provides pure filtering logic with context support:

Filter Flow

Use controls to zoom and pan. Click outside or press Escape to close.

Filter Flow

Reactivity

Property/MethodReactiveNotes
queryShallowRef, updated on each apply()
items (from apply)Computed, filters reactively
Tip

Reactive filtering Both the query and items passed to apply() can be reactive. The filtered result automatically updates when either changes.

Filter Modes

When the query is an array, each mode controls how multiple queries are matched against item values:

ModeBehaviorPasses when
some (default)Iterates all queries and all valuesAny query matches any value
everyIterates all queries and all valuesAll queries match all values
unionJoins values, checks each queryAny query matches the joined string
intersectionJoins values, checks each queryAll queries match the joined string
Tip

some vs union some and union both pass when any query matches, but some checks each value independently while union joins all values into a single string. The difference matters when a match spans multiple fields.

Examples

12 of 12 results
New York/USA
8.3M
Los Angeles/USA
3.9M
London/UK
8.8M
Paris/France
2.2M
Tokyo/Japan
13.9M
Sydney/Australia
5.3M
Toronto/Canada
2.9M
Berlin/Germany
3.6M
Singapore/Singapore
5.5M
Dubai/UAE
3.5M
San Francisco/USA
870K
Amsterdam/Netherlands
870K
<script setup lang="ts">
  import { createFilter } from '@vuetify/v0'
  import { computed, shallowRef } from 'vue'

  const cities = [
    { name: 'New York', country: 'USA', population: '8.3M' },
    { name: 'Los Angeles', country: 'USA', population: '3.9M' },
    { name: 'London', country: 'UK', population: '8.8M' },
    { name: 'Paris', country: 'France', population: '2.2M' },
    { name: 'Tokyo', country: 'Japan', population: '13.9M' },
    { name: 'Sydney', country: 'Australia', population: '5.3M' },
    { name: 'Toronto', country: 'Canada', population: '2.9M' },
    { name: 'Berlin', country: 'Germany', population: '3.6M' },
    { name: 'Singapore', country: 'Singapore', population: '5.5M' },
    { name: 'Dubai', country: 'UAE', population: '3.5M' },
    { name: 'San Francisco', country: 'USA', population: '870K' },
    { name: 'Amsterdam', country: 'Netherlands', population: '870K' },
  ]

  const query = shallowRef('')
  const filter = createFilter({ keys: ['name', 'country'] })
  const { items } = filter.apply(query, cities)

  function highlight (text: string) {
    if (!query.value) return text
    const regex = new RegExp(`(${query.value})`, 'gi')
    return text.replace(regex, '<mark class="bg-warning text-on-warning rounded px-0.5">$1</mark>')
  }

  const hasResults = computed(() => items.value.length > 0)
</script>

<template>
  <div class="flex flex-col gap-4">
    <div class="relative">
      <input
        v-model="query"
        class="w-full px-4 py-3 pl-10 border border-divider bg-surface text-on-surface rounded-lg focus:border-primary focus:outline-none transition-colors"
        placeholder="Search cities or countries..."
        type="text"
      >
      <svg
        class="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 opacity-40"
        fill="none"
        stroke="currentColor"
        viewBox="0 0 24 24"
      >
        <path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" />
      </svg>
    </div>

    <div class="flex items-center justify-between text-sm opacity-60">
      <span>{{ items.length }} of {{ cities.length }} results</span>
      <span v-if="query" class="font-mono text-xs">{{ `"${query}"` }}</span>
    </div>

    <div class="border border-divider rounded-lg overflow-hidden divide-y divide-divider">
      <div
        v-for="city in items"
        :key="city.name"
        class="px-4 py-3 flex items-center justify-between hover:bg-surface-tint transition-colors"
      >
        <div>
          <span class="font-medium" v-html="highlight(city.name)" />
          <span class="mx-2 opacity-30">/</span>
          <span class="text-sm opacity-70" v-html="highlight(city.country)" />
        </div>
        <span class="text-sm font-mono opacity-50">{{ city.population }}</span>
      </div>

      <div
        v-if="!hasResults"
        class="px-4 py-8 text-center opacity-50"
      >
        No cities found matching "{{ query }}"
      </div>
    </div>
  </div>
</template>

API Reference

The following API details are for the createFilter composable.

Functions

createFilter

(options?: FilterOptions) => E

Creates a filter context with pre-configured options.

createFilterContext

(_options?: FilterContextOptions) => ContextTrinity<E>

Creates a filter context with dependency injection support.

useFilter

(namespace?: string) => E

Returns the current filter context from dependency injection.

Options

customFilter

FilterFunction | undefined

keys

string[] | undefined

mode

FilterMode | undefined

Properties

mode

FilterMode

The filter mode

keys

string[] | undefined

Keys to filter on for object items

customFilter

FilterFunction | undefined

Custom filter function

query

ShallowRef<Primitive | Primitive[]>

Current query ref

Methods

apply

<T extends Z>(query: FilterQuery, items: MaybeRefOrGetter<T[]>) => FilterResult<T>

Apply filter to an array of items

Benchmarks

Every operation is profiled across multiple dataset sizes to measure real-world throughput. Each benchmark is assigned a performance tier—good, fast, blazing, or slow—and groups are scored by averaging their individual results so you can spot bottlenecks at a glance. This transparency helps you make informed decisions about which patterns scale for your use case. Learn more in the benchmarks guide.

View benchmark source↗

Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/