Filtering Examples
This page demonstrates the filtering capabilities of FloTable with practical examples.
Basic Filtering Setup
import { TableWithViews } from 'flo-table-with-views';
import type { ProColumns } from '@ant-design/pro-components';
interface Product {
id: string;
name: string;
category: string;
price: number;
status: 'active' | 'inactive' | 'pending';
createdAt: string;
}
const columns: ProColumns<Product>[] = [
{
title: 'Product Name',
dataIndex: 'name',
valueType: 'text',
},
{
title: 'Category',
dataIndex: 'category',
valueType: 'select',
valueEnum: {
electronics: 'Electronics',
clothing: 'Clothing',
books: 'Books',
home: 'Home & Garden',
},
},
{
title: 'Price',
dataIndex: 'price',
valueType: 'money',
},
{
title: 'Status',
dataIndex: 'status',
valueType: 'select',
valueEnum: {
active: { text: 'Active', status: 'Success' },
inactive: { text: 'Inactive', status: 'Error' },
pending: { text: 'Pending', status: 'Processing' },
},
},
{
title: 'Created Date',
dataIndex: 'createdAt',
valueType: 'date',
},
];
// Mock data request function
const fetchProducts = async (params: any, sort: any, filter: any) => {
const { current = 1, pageSize = 10 } = params;
const { filters = {} } = filter;
// Simulate API call with filtering
let filteredData = mockProductData;
// Apply search filter
if (filters.search) {
const searchTerm = filters.search.toLowerCase();
filteredData = filteredData.filter(item =>
item.name.toLowerCase().includes(searchTerm) ||
item.category.toLowerCase().includes(searchTerm)
);
}
// Apply status filter
if (filters.status) {
filteredData = filteredData.filter(item => item.status === filters.status);
}
// Apply category filter
if (filters.category) {
filteredData = filteredData.filter(item => item.category === filters.category);
}
// Apply pagination
const startIndex = (current - 1) * pageSize;
const endIndex = startIndex + pageSize;
const paginatedData = filteredData.slice(startIndex, endIndex);
return {
data: paginatedData,
success: true,
total: filteredData.length,
};
};
export default function ProductTable() {
return (
<TableWithViews
id="products-table"
title="Product Management"
description="Manage your product inventory with advanced filtering"
columns={columns}
request={fetchProducts}
initQuickFilterColumns={['name', 'category']} // Enable quick filters for these columns
views={[
{
key: 'all',
label: 'All Products',
shortLabel: 'All',
query: '',
filters: {},
},
{
key: 'active',
label: 'Active Products',
shortLabel: 'Active',
query: 'status:active',
filters: { status: 'active' },
},
{
key: 'electronics',
label: 'Electronics',
shortLabel: 'Electronics',
query: 'category:electronics',
filters: { category: 'electronics' },
},
]}
/>
);
}
Advanced Filtering with Custom Request Handler
const advancedFetchProducts = async (params: any, sort: any, filter: any) => {
const { current = 1, pageSize = 10 } = params;
const { filters = {} } = filter;
// Build query parameters
const queryParams = new URLSearchParams({
page: current.toString(),
limit: pageSize.toString(),
});
// Add filter parameters
Object.entries(filters).forEach(([key, value]) => {
if (value && key !== 'search') {
queryParams.append(key, value);
}
});
// Handle search separately (might search across multiple fields)
if (filters.search) {
queryParams.append('q', filters.search);
}
// Add sorting
if (sort && Object.keys(sort).length > 0) {
const sortField = Object.keys(sort)[0];
const sortOrder = sort[sortField] === 'ascend' ? 'asc' : 'desc';
queryParams.append('sort', `${sortField}:${sortOrder}`);
}
try {
const response = await fetch(`/api/products?${queryParams}`);
const data = await response.json();
return {
data: data.items,
success: true,
total: data.total,
};
} catch (error) {
return {
data: [],
success: false,
total: 0,
};
}
};
Filter State Management
import { useState, useCallback } from 'react';
export default function ProductTableWithState() {
const [filterState, setFilterState] = useState({});
const handleFilterChange = useCallback((newFilters: any) => {
setFilterState(newFilters);
// Optionally persist to localStorage or URL params
localStorage.setItem('productFilters', JSON.stringify(newFilters));
}, []);
return (
<TableWithViews
id="products-table-with-state"
title="Products with Persistent Filters"
columns={columns}
request={fetchProducts}
initQuickFilterColumns={['name', 'category', 'status']}
// The table manages its own filter state internally
/>
);
}
Filter Types and ValueTypes
Different column valueType configurations enable different filter UI components:
text- Text input for free-form searchselect- Dropdown with predefined options (requiresvalueEnum)date- Date picker for date filteringdateRange- Date range pickerdigit- Numeric input with validationmoney- Currency input with formattingpercent- Percentage input
const columnsWithDifferentTypes: ProColumns<Product>[] = [
{
title: 'Product Name',
dataIndex: 'name',
valueType: 'text', // Text input filter
},
{
title: 'Price Range',
dataIndex: 'priceRange',
valueType: 'digitRange', // Number range filter
},
{
title: 'Launch Date',
dataIndex: 'launchDate',
valueType: 'dateRange', // Date range filter
},
{
title: 'Discount',
dataIndex: 'discount',
valueType: 'percent', // Percentage filter
},
];
Tips for Optimal Filtering Performance
-
Debounce Search Input: The search input automatically debounces user input to avoid excessive API calls.
-
Server-Side Filtering: Always implement filtering on the server side for large datasets.
-
Index Searchable Fields: Ensure your database has proper indexes on frequently filtered columns.
-
Use Views for Common Filters: Pre-configure common filter combinations as views for better UX.
-
Clear Filter State: Provide easy ways for users to clear all filters and return to the default view.