Facets container
The Facets container lists and manages search filters (facets) to refine product search results.
Import
import Facets from '@dropins/storefront-product-discovery/containers/Facets.js';
Configurations
The Facets
container provides the following configuration options:
Basic Usage
// Basic facets containerawait provider.render(Facets)($container);
// With scope and callbackawait provider.render(Facets, { scope: 'popover', onFilterChange: (filters) => { console.log('Filters changed:', filters); }})($container);
Slots
The Facets
container supports several customization slots. For detailed information about available slots and their usage, see Product Discovery Slots.
Example Slot Usage
slots: { FacetBucketLabel: (ctx) => { // Here we are overriding the default Facet labels. const $label = document.createElement('span'); $label.innerText = `${ctx.data.name ?? ctx.data.title} (${ctx.data.count})`;
// If the facet has an icon, add it to the label if (ctx.data.icon) { const $icon = document.createElement('img'); $icon.className = 'facet-bucket-label__icon'; $icon.src = ctx.data.icon; $label.prepend($icon); }
ctx.replaceWith($label); },}
Real-time Updates
The container automatically updates when search events are received:
- Search Results: Updates available facets based on results
- Filter Changes: Automatically triggers new searches with updated filters
Scope Support
The Facets container supports isolated instances through scope configuration:
// Global scope (default) Listens to all search eventsawait provider.render(Facets)($container);
// Only listens to events with scope: 'popover'await provider.render(Facets, { scope: 'popover' })($container);
Selected Filters Display
- Shows all currently selected filters as removable buttons
- Displays filter labels with appropriate formatting (including currency for price ranges)
- Provides individual remove functionality for each selected filter
Clear All Functionality
- “Clear All” button to remove all selected filters at once
- Automatically triggers a new search with no filters applied
Integration Examples
Basic PLP Setup
await provider.render(Facets)($facetsContainer);
Category-Based Filtering
await provider.render(Facets, { onFilterChange: (filters) => { console.log('Electronics filters changed:', filters); }})($electronicsFacets);
Scoped Facets
await provider.render(Facets, { scope: 'popover', onFilterChange: (filters) => { // Quick search filters console.log('Popover filters:', filters); }})($popoverFacets);
Best Practices
- Scope Management: Use unique scope identifiers for multiple instances
- Scope Configuration: Use appropriate scope identifiers for multiple instances
- Filter Callbacks: Use
onFilterChange
for custom filter handling - Real-time Updates: Let the container handle updates automatically
- Performance: Use scoping to limit unnecessary updates
- Slot Customization: Use slots for merchant-specific facet styling
Troubleshooting
Common Issues
- Container Not Updating: Check scope configuration and event handling
- Slots Not Rendering: Ensure the element is added to the slot using
ctx.appendChild()
,ctx.replaceWith()
, etc. - Performance Issues: Use proper scoping to limit unnecessary updates
- Styling Conflicts: Use specific CSS classes to avoid conflicts
Facet Selection Behavior
- Dynamic Facets: Facets are automatically generated based on search results and available product attributes.
- Category-Relative Filtering: If a
categoryPath
is provided in the search, facet selections will automatically include the categoryPath to ensure filters are relative to the current category.