Skip to Content
FrontendPlatformDynamic Filters System

Dynamic Filters System

The dynamic filters system provides a flexible way to handle filtering of data based on attributes passed from the backend. It supports multiple filter types and automatically generates the appropriate UI components.

Core Components

1. DynamicFilters Component

The main component that orchestrates the filter system. It accepts:

  • attributes: Object containing filterable attributes
  • dimensions: Current dimension values for the filters
  • onChange: Callback when filters change
  • initialValues: Initial filter values
  • manual: Boolean to control if validation is manual or automatic
<DynamicFilters attributes={attributes} dimensions={dimensions} onChange={handleFiltersChanged} initialValues={initialFilters} manual={false} />

2. Filter Types

The system supports two main types of filters:

Select-like Filters

  • ButtonGroup
  • Select
  • Toggle
  • ComboBox
  • Input
  • Checkbox
  • CheckboxList

Range Filters

  • RangeSlider
  • NumberComparison

3. AdaptiveNumericFilter Component

The AdaptiveNumericFilter component intelligently switches between different numeric filter UI components based on available dimension data:

  • RangeSlider: Used when dimensions provide min/max bounds, allowing users to select a range within known limits
  • NumberComparison: Used when dimension data is unavailable or insufficient, providing comparison operators (equals, greater than, less than, etc.)
<AdaptiveNumericFilter attribute={attribute} dimensions={dimensions} fieldAtom={fieldAtom} />

The component automatically determines which UI to render based on the presence and validity of dimension values.

Feature Flag Integration

Attributes can be conditionally displayed based on feature flags. Each attribute can have an optional featureFlag property that controls its visibility:

interface Attribute { name: string type: string featureFlag?: string // Optional feature flag name // ... other properties }

The filter system checks feature flags using the pattern:

!attribute.featureFlag || hasVariant(attribute.featureFlag)

This means:

  • If no featureFlag is specified, the filter is always shown
  • If a featureFlag is specified, the filter is only shown when that feature flag is enabled (via hasVariant)

This allows for gradual rollout of new filter capabilities or A/B testing of filter options.

Data Flow

  1. Backend to Frontend

    • Backend provides attributes with their types and possible values
    • Dimensions contain current possible values and counts
    • Initial values can be provided to pre-populate filters
  2. Filter State Management

    • Uses Jotai for state management
    • filterAtom: Stores current filter values
    • fieldAtomsAtom: Maintains form field states
  3. Filter Generation

    // Convert attributes to filter format attributesToFilters( attributesWithNames, dimensions, values, touchedFields )

Key Hooks

useFilterableAttributes

Filters out unsupported attributes and returns a tuple of attribute name and attribute.

const filteredAttributes = useFilterableAttributes(attributes)

useDynamicFormAtom

Generates a form atom based on the filterable attributes.

const formAtom = useDynamicFormAtom(attributesWithNames)

useFilters

Converts form values to backend-compatible filters.

const filters = useFilters( attributesWithNames, dimensions, formAtom )

useAttributeInfo

Retrieves attribute metadata including display name, type, and configuration options.

const { displayName, type, options } = useAttributeInfo(attributeKey, attributes)

useFilterValueTransform

Transforms filter values between internal format and display format. Handles value normalization and conversion for different filter types.

const { toDisplay, toInternal } = useFilterValueTransform(attribute)

useScreenSize

Detects current screen size for responsive filter layouts. Returns breakpoint information used to adapt filter presentation on mobile vs desktop.

const { isMobile, isTablet, isDesktop } = useScreenSize()

Filter Conversion

Select-like Filters

Converted to enum filters with OR operations:

{ [attributeName]: { op: "OR", values: ["value1", "value2"] } }

Range Filters

Converted to range filters with min/max values:

{ [attributeName]: { min: number, max: number } }

Styling

The system supports various style customizations:

interface DynamicFiltersStyleProps { layout?: 'vertical' | 'horizontal' filterLayout?: 'vertical' | 'horizontal' separator?: boolean compact?: boolean fixedWidth?: boolean }

Usage Example

const MyComponent = () => { const handleFiltersChanged = (filters: Filters) => { // Handle filter changes } return ( <DynamicFilters attributes={myAttributes} dimensions={myDimensions} onChange={handleFiltersChanged} dynamicFilters={{ layout: 'vertical', filterLayout: 'horizontal', separator: true }} /> ) }

Best Practices

  1. Always provide dimensions when available to show counts
  2. Use manual mode when you need to control when filters are applied
  3. Consider mobile responsiveness when choosing layouts

Error Handling

The system handles several edge cases:

  • Missing dimensions
  • Invalid filter values
  • Uninitialized form fields
  • Range values outside bounds

Remember to validate filter outputs before sending to the backend.

Last updated on