The URL Manager handles state persistence through URL parameters, enabling shareable filter states and browser history integration.
- Installation
- Basic Usage
- Configuration
- URL Parameter Format
- API Reference
- Events
- Examples
- TypeScript
- Best Practices
import { URLManager } from 'advanced-filter-system';
// As part of AFS
const afs = createAFS({
urlStateEnabled: true
});
// Access URL manager
const urlManager = afs.urlManager;
const afs = createAFS({
urlStateEnabled: true,
urlStateKey: 'filter', // Optional URL prefix
urlStateDelay: 100 // Delay before initial state load
});
// Handle browser navigation
window.addEventListener('popstate', () => {
afs.urlManager.loadFromURL();
});
{
enabled: boolean; // Enable URL state
stateKey?: string; // URL parameter prefix
delay?: number; // Initial load delay
pushState?: boolean; // Use pushState or replaceState
encodeValues?: boolean; // URL encode parameter values
parameterMapping?: { // Custom parameter names
filter: string;
search: string;
sort: string;
page: string;
}
}
// Example URL structure
?category=electronics,books // Filters
&price=100,500 // Range filter
&search=laptop // Search query
&sort=price,desc // Sort state
&page=2 // Pagination
// Filter parameters
category=value1,value2 // Multiple values
filterMode=and // Filter mode
groupMode=or // Group mode
// Range parameters
range_price=0,1000 // Numeric range
dateRange_published=2024-01-01,2024-12-31 // Date range
// Search parameter
search=query // Search query
// Sort parameters
sort=key,direction // Sort state
// Pagination parameters
page=2 // Current page
perPage=20 // Items per page
Update URL with current state.
afs.urlManager.updateURL();
Load state from URL parameters.
afs.urlManager.loadFromURL();
Clear all URL parameters.
afs.urlManager.clearURL();
Get current URL parameters.
const params = afs.urlManager.getURLParams();
Get specific parameter value.
const searchQuery = afs.urlManager.getParam('search');
Check if URL has any parameters.
if (afs.urlManager.hasParams()) {
// Handle parameters
}
interface URLState {
filters: string[];
ranges: Map<string, Range>;
dateRanges: Map<string, DateRange>;
search: string;
sort: SortState;
page: number;
}
// URL state loaded
afs.on('urlStateLoaded', (data) => {
console.log('Loaded state:', data.params);
});
// URL updated
afs.on('urlUpdated', (data) => {
console.log('New URL:', data.url);
});
// URL cleared
afs.on('urlCleared', () => {
console.log('URL state cleared');
});
// Update URL when state changes
afs.on('filter', () => {
afs.urlManager.updateURL();
});
afs.on('search', () => {
afs.urlManager.updateURL();
});
afs.on('sort', () => {
afs.urlManager.updateURL();
});
// Save complete filter state
function saveCompleteState() {
const state = {
filters: Array.from(afs.filter.getActiveFilters()),
search: afs.search.getValue(),
sort: afs.sort.getCurrentSort(),
page: afs.pagination.getPageInfo().currentPage
};
afs.urlManager.updateURL();
}
// Restore complete state
function restoreCompleteState() {
afs.urlManager.loadFromURL();
}
// Custom parameter processing
afs.urlManager.processCustomParam = (key, value) => {
if (key === 'custom') {
// Handle custom parameter
return processCustomValue(value);
}
return value;
};
// Create shareable URL
function getShareableURL() {
afs.urlManager.updateURL();
return window.location.href;
}
// Share button implementation
const shareButton = document.createElement('button');
shareButton.addEventListener('click', () => {
const url = getShareableURL();
navigator.clipboard.writeText(url);
alert('URL copied to clipboard!');
});
interface URLManagerOptions {
enabled: boolean;
stateKey?: string;
delay?: number;
pushState?: boolean;
encodeValues?: boolean;
parameterMapping?: ParameterMapping;
}
interface ParameterMapping {
filter: string;
search: string;
sort: string;
page: string;
}
interface URLStateEvent {
params: Record<string, string>;
source: 'url' | 'history';
}
interface URLUpdateEvent {
url: string;
state: URLState;
}
-
State Serialization
// Efficient state serialization function serializeState(state) { return Object.entries(state) .filter(([_, value]) => value !== null && value !== undefined) .map(([key, value]) => `${key}=${encodeURIComponent(value)}`) .join('&'); }
-
History Management
// Handle browser navigation properly window.addEventListener('popstate', (event) => { if (event.state) { afs.urlManager.loadFromURL(true); // Skip history update } });
-
Error Handling
try { afs.urlManager.loadFromURL(); } catch (error) { console.error('URL state error:', error); afs.urlManager.clearURL(); // Reset to clean state }
-
Performance
// Debounce URL updates const debouncedUpdate = debounce(() => { afs.urlManager.updateURL(); }, 300); afs.on('filter', debouncedUpdate); afs.on('search', debouncedUpdate);
-
Clean URLs
// Remove empty parameters function cleanURL(params) { Array.from(params.entries()).forEach(([key, value]) => { if (!value || value === '[]' || value === '{}') { params.delete(key); } }); return params; }
-
State Validation
// Validate URL parameters function validateURLState(params) { const allowedParams = new Set(['filter', 'search', 'sort', 'page']); let isValid = true; params.forEach((value, key) => { if (!allowedParams.has(key)) { isValid = false; } }); return isValid; }