Skip to content

veebisepad/vue-query-filters

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Vue Query Filters

A lightweight, flexible URL query parameter management system for Vue applications.

npm version license

Works seamlessly with Spatie laravel-query-builder and Inertia.js for filtering and sorting data in Laravel applications.

Table of Contents

Installation

npm install @veebisepad/vue-query-filters

Basic Usage

import { useFilters, createFilterFactory } from '@veebisepad/vue-query-filters';
import { watch } from 'vue';

// Create filter factory
const f = createFilterFactory();

// Define your filters
const filters = useFilters(
    {
        category: f.single(),
        brands: f.multiple(),
        price: f.range(),
    },
    {
        onApply: queryParams => {
            console.log('Filters changed:', queryParams);
            // Fetch data or update URL
        },
    }
);

API Reference

Core Functions

Function Description Parameters Returns
createFilterFactory(options?) Creates a collection of filter factory functions options: Configuration with optional keyTransformer function Filter factory object
useFilters(filters, options?) Creates a reactive filter object filters: Map of filter configurations
options: Optional configuration
Reactive filter object

Configuration Options

createFilterFactory Options

Option Type Description Default
keyTransformer Function Transforms filter keys for URL parameters key => key

Example:

// For Laravel Spatie Query Builder format
const f = createFilterFactory({
    keyTransformer: key => `filter[${key}]`
});

useFilters Options

Option Type Description Default
delimiter String Character used to separate multiple values ','
onApply Function Callback function triggered when filters are applied via get()
preserveQueryOrder Boolean Preserves URL query parameter order when generating query objects true
undefined

Example:

const filters = useFilters(
    { /* filter definitions */ }, 
    { 
        delimiter: ';',
        onApply: queryParams => {
            // Called when filters.get() is invoked
            console.log('Applied filters:', queryParams);
            // Update URL, fetch data, etc.
        }
    }
);

Filter Types

Filter Description Default Value Example
single() Single value filter null f.single('default')
multiple() Array-based filter [] f.multiple(['default'])
range() Filter with from/to values {from: null, to: null} f.range({from: 10, to: 50})
custom() User-defined filter behavior Based on implementation See Custom Filter example

Filter Object Methods

Method Description Parameters Returns
get() Triggers the onApply callback None void
toSearchParams() Converts filters to URLSearchParams None URLSearchParams object
toQueryObject(transformKeys?) Creates object with filter key-values transformKeys: Boolean (default: true) Object with filter parameters
toOrderedQueryObject(transformKeys?) Creates object with filter key-values, preserving URL parameter order transformKeys: Boolean (default: true) Object with ordered filter parameters
data() Returns plain object of filter values None Filter values object
has(filter, value) Checks if value exists in filter filter: Filter key
value: Value to check
Boolean
clear(filterKey, shouldGet?) Resets filter(s) to default filterKey: String/Array of keys
shouldGet: Boolean to trigger onApply
Void
clearAll() Resets all filters None Void
setOptions(newOptions) Updates filter options newOptions: New options object Void

Examples

1. Basic Filter Setup and Usage

const f = createFilterFactory();
const filters = useFilters({
    search: f.single(''),
    category: f.single(null),
    brands: f.multiple([])
});

// Set filter values
filters.search = 'laptop';
filters.category = 'electronics';
filters.brands = ['apple', 'samsung'];

// Check if filter has value
console.log(filters.has('brands', 'apple')); // true

// Get all filter values as query parameters
const queryParams = filters.get();

2. Watching Filter Changes

import { watch } from 'vue';
import { useDebounceFn } from '@vueuse/core';

// Option 1: Simple watcher
watch(
    filters,
    () => filters.get(), // Trigger onApply callback
    { deep: true }
);

// Option 2: Debounced watcher
const debouncedApplyFilters = useDebounceFn(() => {
    filters.get();
}, 300);

watch(filters, () => debouncedApplyFilters(), { deep: true });

3. Resetting Filters

// Reset a single filter
filters.clear('category');

// Reset multiple filters
filters.clear(['brands', 'price']);

// Reset all filters
filters.clearAll();

4. Vue Component Example

<script setup>
import { useFilters, createFilterFactory } from '@veebisepad/vue-query-filters';

const f = createFilterFactory();
const filters = useFilters({
    search: f.single(''),
    categories: f.multiple([]),
    priceRange: f.range({ from: null, to: null })
});

function applyFilters() {
    filters.get();
}
</script>

<template>
    <div>
        <h2>Product Filters</h2>
        
        <!-- Single filter -->
        <input v-model="filters.search" type="text" placeholder="Search products..." />
        
        <!-- Multiple filter -->
        <div>
            <label><input type="checkbox" value="electronics" v-model="filters.categories" /> Electronics</label>
            <label><input type="checkbox" value="clothing" v-model="filters.categories" /> Clothing</label>
        </div>
        
        <!-- Range filter -->
        <div>
            <input v-model.number="filters.priceRange.from" type="number" placeholder="Min" />
            <input v-model.number="filters.priceRange.to" type="number" placeholder="Max" />
        </div>
        
        <button @click="applyFilters">Apply Filters</button>
        <button @click="filters.clearAll()">Reset All</button>
    </div>
</template>

5. Custom Filter Implementation

import { createFilterFactory, useFilters } from '@veebisepad/vue-query-filters';

// 1) Create a filter factory
const factory = createFilterFactory();

// 2) Define a custom filter
const myCustomFilter = factory.custom({
    defaultValue: 123,
    parseQueryParam(value, delimiter) {
        // Expected to parse 'enabled,value' from the incoming query string
        // and return the parsed filter value
    },
    serializeQueryParam(currentValue, delimiter) {
        // Expected to generate a string for the URL query parameter
        // or return null if the filter is inactive
    },
    hasValue(filterValue, candidate) {
        // Expected to determine if the current filter value
        // 'matches' a given candidate
    },
});

// 3) Implement the custom filter in useFilters
const filters = useFilters(
    {
        specialSetting: myCustomFilter,
    },
    {
        onApply(queryParams) {
            // Triggered when filters.get() is called
            console.log('Custom filter changed:', queryParams);
        },
    }
);

// 4) Use the custom filter
filters.specialSetting = 234;
filters.get(); // calls onApply with updated query params

6. Using with Laravel and Inertia.js

import { useFilters, createFilterFactory } from '@veebisepad/vue-query-filters';
import { router } from '@inertiajs/vue3';
import { watch } from 'vue';

// Create filter factory with key transformer for Laravel Query Builder
const f = createFilterFactory({
    keyTransformer: key => `filter[${key}]`
});

const filters = useFilters(
    {
        name: f.single(),
        category: f.multiple(),
        price: f.range(),
        sort: f.single('-created_at')
    },
    {
        onApply: queryParams => {
            // Navigate with Inertia preserving state
            router.visit(route('products.index', queryParams), {
                preserveState: true,
                preserveScroll: true,
                only: ['products']
            });
        }
    }
);

// Auto-apply filters when they change
watch(filters, () => filters.get(), { deep: true });

TypeScript Support

import { useFilters, createFilterFactory } from '@veebisepad/vue-query-filters';
import type { SingleFilter, MultipleFilter, RangeFilter } from '@veebisepad/vue-query-filters';

const f = createFilterFactory();

const filters = useFilters({
    category: f.single<string>('all'),
    brands: f.multiple<string>([]),
    price: f.range<number>({ from: null, to: null }),
});

License

MIT

About

Reactive utility for managing URL query parameters

Resources

License

Stars

Watchers

Forks

Packages

No packages published