Fuzzy Filtering Guide
Examples & API
Guide
Fuzzy filtering is a technique that allows you to filter data based on approximate matches. This can be useful when you want to search for data that is similar to a given value, rather than an exact match.
You can implement client-side fuzzy filtering by defining a custom filter function. This function should take in the row, columnId, and filter value, and return a boolean indicating whether the row should be included in the filtered data.
Fuzzy filtering is mostly used with global filtering, but you can also apply it to individual columns. We will discuss how to implement fuzzy filtering for both cases.
NOTE
You will need to install a fuzzy matching library like fuzzysort to use fuzzy filtering. Fuzzy matching libraries provide algorithms for approximate string matching, which is useful for implementing search functionality that is more forgiving of typos and variations.
Using a fuzzy matching library is optional, but libraries like fuzzysort provide a great way to both fuzzy filter and sort by the match score, so that rows can be sorted by their closest matches to the search query.
Defining a Custom Fuzzy Filter Function
Here's an example of a custom fuzzy filter function using fuzzysort:
import Fuzzysort from "fuzzysort"
import type {FilterFn} from "@qualcomm-ui/core/table"
const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
// Get the search value
const itemValue = row.getValue(columnId)
// Perform fuzzy search
const result = Fuzzysort.single(value, String(itemValue))
// Store the result score for sorting
addMeta({score: result?.score ?? -Infinity})
// Return if the item should be filtered in/out
return result !== null
}In this function, we're using the Fuzzysort.single function from the fuzzysort library to perform fuzzy matching. We then store the match score in the meta data of the row, and return whether the item matched the search criteria.
Using Fuzzy Filtering with Global Filtering
To use fuzzy filtering with global filtering, you can specify the fuzzy filter function in the globalFilterFn option of the table instance:
import {useReactTable} from "@qualcomm-ui/react/table"
import {
getCoreRowModel,
getFilteredRowModel,
getSortedRowModel,
} from "@qualcomm-ui/core/table"
const table = useReactTable({
columns,
data,
filterFns: {
fuzzy: fuzzyFilter, // define as a filter function that can be used in column definitions
},
globalFilterFn: "fuzzy", // apply fuzzy filter to the global filter (most common use case for fuzzy filter)
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(), // client side filtering
getSortedRowModel: getSortedRowModel(), // client side sorting needed if you want to use sorting too
})Using Fuzzy Filtering with Column Filtering
To use fuzzy filtering with column filtering, you should first define the fuzzy filter function in the filterFns option of the table instance. You can then specify the fuzzy filter function in the filterFn option of the column definition:
const column = [
{
accessorFn: (row) => `${row.firstName} ${row.lastName}`,
id: "fullName",
header: "Full Name",
cell: (info) => info.getValue(),
filterFn: "fuzzy", // using our custom fuzzy filter function
},
// other columns...
]In this example, we're applying the fuzzy filter to a column that combines the firstName and lastName fields of the data.
Sorting with Fuzzy Filtering
When using fuzzy filtering with column filtering, you might also want to sort the data based on the match score. You can do this by defining a custom sorting function:
import {type SortingFn, sortingFns} from "@qualcomm-ui/core/table"
const fuzzySort: SortingFn<any> = (rowA, rowB, columnId) => {
let dir = 0
// Only sort by score if the column has score information
if (rowA.columnFiltersMeta[columnId]) {
const scoreA = rowA.columnFiltersMeta[columnId]?.score ?? -Infinity
const scoreB = rowB.columnFiltersMeta[columnId]?.score ?? -Infinity
// Higher scores are better matches in fuzzysort
dir = scoreB - scoreA
}
// Provide an alphanumeric fallback for when the scores are equal
return dir === 0 ? sortingFns.alphanumeric(rowA, rowB, columnId) : dir
}In this function, we're comparing the match scores of the two rows. Higher scores indicate better matches. If the scores are equal, we fall back to alphanumeric sorting.
You can then specify this sorting function in the sortFn option of the column definition:
export const fullNameColumn = {
accessorFn: (row) => `${row.firstName} ${row.lastName}`,
id: "fullName",
header: "Full Name",
cell: (info) => info.getValue(),
filterFn: "fuzzy", // using our custom fuzzy filter function
sortFn: "fuzzySort", // using our custom fuzzy sort function
}