Skip to main content

TreeViewFilter

A hierarchical tree-based filter component that allows users to browse, search, and select multiple categories from a nested structure. Perfect for filtering data with hierarchical categories or implementing multi-level navigation.

Features

  • Hierarchical category browsing with expandable/collapsible nodes
  • Multi-select functionality with checkbox selection
  • Real-time search capabilities across all category levels
  • "Show selected only" toggle for focused viewing
  • Customizable tag display with limiting options
  • Comprehensive event tracking system
  • Controlled and uncontrolled component modes
  • Accessibility support with keyboard navigation

Props

Required Props

PropTypeDescription
idstringUnique identifier for the component (required for Dash callbacks)
categoriesarrayArray of category objects with the structure: { id: string, name: string, children?: Category[] }

Optional Props

PropTypeDefaultDescription
defaultSelectedIdsstring[][]Initial selected category IDs (uncontrolled mode)
selectedIdsstring[][]Currently selected category IDs (controlled mode)
isOpenbooleanfalseControls whether the filter dropdown is open
labelstring"Categories"Label text for the component
placeholderstring"Select categories..."Placeholder text when no categories are selected
searchPlaceholderstring"Search categories..."Placeholder text for the search field
applyButtonTextstring"Apply"Text for the apply button
cancelButtonTextstring"Cancel"Text for the cancel button
limitTagsnumber2Maximum number of tags to display before showing "+N". Set to -1 to show all tags
collapseIdenticalPathsbooleanfalseWhether to collapse paths with identical names in the hierarchy
switchLabelstring"Show selected only"Label for the "Show selected only" switch
maxTrackingEventsnumber100Maximum number of events to keep in tracking history
chipLabelMaxWidthstring"100px"Maximum width of the chip label before truncating

Category Structure

Each category in the categories array should have the following structure:

{
"id": "unique_id",
"name": "Category Name",
"children": [
{
"id": "child_id",
"name": "Child Category",
"children": [...]
},
...
]
}

Events

The component tracks various user interactions through the trackingEvents prop. Each event has the following structure:

{
eventType: string; // Type of event (e.g., "select_item", "search", "apply")
timestamp: number; // Unix timestamp
payload: {
nodeId?: string; // ID of affected node
nodeName?: string; // Name of affected node
searchQuery?: string; // Search query
selectedItems?: string[]; // Selected item IDs
isSelected?: boolean; // Selection state
isExpanded?: boolean; // Expansion state
showSelectedOnly?: boolean; // Show selected only state
}
}

Event types include:

  • expand_node
  • collapse_node
  • select_item
  • deselect_item
  • apply
  • cancel
  • clear_all
  • search
  • toggle_selected_only
  • open_menu
  • close_menu

Usage Example

import dash
from dash import html
import yipit_dash_mui_components as dmc

app = dash.Dash(__name__)

# Define your category structure
categories = [
{
"id": "electronics",
"name": "Electronics",
"children": [
{
"id": "computers",
"name": "Computers",
"children": [
{"id": "laptops", "name": "Laptops"},
{"id": "desktops", "name": "Desktops"}
]
},
{"id": "phones", "name": "Phones"}
]
},
{
"id": "books",
"name": "Books",
"children": [
{"id": "fiction", "name": "Fiction"},
{"id": "nonfiction", "name": "Non-Fiction"}
]
}
]

app.layout = dmc.YipitMUIProvider(
children=[
html.Div([
dmc.TreeViewFilter(
id="category-filter",
categories=categories,
defaultSelectedIds=[],
selectedIds=["ultrabooks", "gaming_desktops", "headphones"],
isOpen=False,
label="Categories",
placeholder="Select categories...",
searchPlaceholder="Search categories...",
applyButtonText="Apply Filters",
cancelButtonText="Cancel",
limitTags=1,
collapseIdenticalPaths=True,
switchLabel="Show selected only",
maxTrackingEvents=10,
chipLabelMaxWidth="50px" # This will truncate long category names in chips
)
])
]
)

if __name__ == "__main__":
app.run_server(debug=True)

Callback Example

from dash import Input, Output, callback

# Callback to handle selected categories
@callback(
Output("output-div", "children"),
Input("category-filter", "selectedIds")
)
def update_output(selected_ids):
if not selected_ids:
return "No categories selected"
return f"Selected categories: {', '.join(selected_ids)}"

# Callback to track user interactions
@callback(
Output("events-div", "children"),
Input("category-filter", "trackingEvents")
)
def display_events(events):
if not events:
return "No events recorded"
return [
html.Div(f"Event: {event['eventType']} - {event['payload']}")
for event in events
]

Best Practices

  1. Always provide unique id props when using multiple TreeViewFilter components
  2. Use defaultSelectedIds for initial selection, and selectedIds for controlled behavior
  3. Consider using limitTags to prevent overflow when many items are selected
  4. Use collapseIdenticalPaths=True when dealing with deep hierarchies that might have repeated names
  5. Monitor trackingEvents to understand user interaction patterns

Notes

  • The component maintains its own state for selections but can also be controlled through props
  • Search functionality is case-insensitive and searches through both IDs and names
  • The "Show selected only" toggle helps users focus on their selections
  • Event tracking is limited by maxTrackingEvents to prevent memory issues

Performance Considerations

  1. Large Category Trees

    • For large category structures, consider using collapseIdenticalPaths
    • The search function indexes all category names and IDs for quick lookup
    • Event tracking is capped by maxTrackingEvents to prevent memory issues
  2. Selection Management

    • Use controlled mode (selectedIds) for complex state management
    • The limitTags prop helps manage visual clutter with many selections