API Reference / Android Widgets / Dynamic Facets
Widget signature
DynamicFacetListConnector(
  searcher: SearcherIndex,
  filterState: FilterState,
  orderedFacets: List<AttributedFacets>,
  selections: SelectionsPerAttribute,
  selectionModeForAttribute: Map<Attribute, SelectionMode>,
  filterGroupForAttribute: Map<Attribute, FilterGroupDescriptor>
)

About this widget

DynamicFacetsListView is a view that displays the ordered list of facets and facet values. The order of groups and facet values in each group defined by the corresponding settings of the index and may be altered by a Rule. You can configure the facet merchandising through the corresponding index setting.

Requirements

  • You must set the attributesForFaceting and configure the facet order, either using the dashboard or using attributesForFaceting and renderingContent respectively with the API.
  • You must set the facets property of the query via Searcher.indexQueryState.query.facets and provide the facet attributes you want to retrieve.

Examples

Instantiate a DynamicFacetsListConnector, set the query facets and launch an initial search on its searcher.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class MyActivity : AppCompatActivity() {
     val client = ClientSearch(
            ApplicationID("YourApplicationID"),
            APIKey("YourSearchOnlyAPIKey"),
    )
    val index = client.initIndex(IndexName("YourIndexName"))
    val searcher = SearcherSingleIndex(index)
    val filterState = FilterState()
    val color = Attribute("color")
    val country = Attribute("country")
    val brand = Attribute("brand")
    val size = Attribute("size")
    val dynamicFacets = DynamicFacetListConnector(
            searcher = searcher,
            filterState = filterState,
            selectionModeForAttribute = mapOf(
                    color to SelectionMode.Multiple,
                    country to SelectionMode.Multiple
            ),
            filterGroupForAttribute = mapOf(
                    brand to (brand to FilterOperator.Or),
                    color to (color to FilterOperator.Or),
            )
    )
    val connection = ConnectionHandler(dynamicFacets)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val dynamicFacetListView = DynamicFacetListAdapter(DynamicFacetListViewHolderImpl.Factory) // implementation of `DynamicFacetListView`
        connection += dynamicFacets.connectView(dynamicFacetListView)
        searcher.query.facets = setOf(brand, color, size, country)
        searcher.searchAsync()
    }

    override fun onDestroy() {
        super.onDestroy()
        searcher.cancel()
        connection.clear()
    }
}

Parameters

searcher
type: SearcherIndex
Required

The Searcher that handles your searches.

filterState
type: FilterState
Required

The FilterState that holds your filters.

orderedFacets
type: List<AttributedFacets>
default: []
Optional

The ordered list of attributed facets.

selections
type: SelectionsPerAttribute
default: []
Optional

The mapping between a facet attribute and a set of selected facet values.

selectionModeForAttribute
type: Map<Attribute, SelectionMode>
default: [:]
Optional

The mapping between a facet attribute and a facet values selection mode. If not provided, the default selection mode is Single.

filterGroupForAttribute
type: Map<Attribute, FilterGroupDescriptor>
default: [:]
Optional

The mapping between a facet attribute and a descriptor of a filter group where the corresponding facet filters are stored in the filter state.

View

view
type: DynamicFacetListView
Required

The view that render the dynamic facets list.

1
2
3
val facetListAdapter = FacetListAdapter(FacetListViewHolderImpl.Factory)
val facetListPresenter = FacetListPresenterImpl(listOf(FacetSortCriterion.CountDescending, FacetSortCriterion.AlphabeticalAscending))
facetListCategory.connectView(facetListAdapter, facetListPresenter)

Low-level API

If you want to fully control the DynamicFacetsList components and connect them manually, you can use the following components:

  • Searcher: the Searcher that handles your searches.
  • FilterState: the current state of the filters.
  • DynamicFacetsListViewModel: dynamic facets business logic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class MyActivity : AppCompatActivity() {
    val client = ClientSearch(
            ApplicationID("YourApplicationID"),
            APIKey("YourSearchOnlyAPIKey"),
    )
    val index = client.initIndex(IndexName("YourIndexName"))
    val searcher = SearcherSingleIndex(index)
    val filterState = FilterState()
    val color = Attribute("color")
    val country = Attribute("country")
    val brand = Attribute("brand")
    val size = Attribute("size")
    val dynamicFacetViewModel = DynamicFacetListViewModel(
          selectionModeForAttribute = mapOf(
                  color to SelectionMode.Multiple,
                  country to SelectionMode.Multiple
          )
  )
    val connection = ConnectionHandler(dynamicFacets)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        connection += dynamicFacetViewModel.connectSearcher(searcher)
        connection += dynamicFacetViewModel.connectFilterState(filterState, mapOf(
                brand to (brand to FilterOperator.Or),
                color to (color to FilterOperator.Or))
        )
        val dynamicFacetListView = DynamicFacetListAdapter(DynamicFacetListViewHolderImpl.Factory) // implementation of `DynamicFacetListView`
        connection += dynamicFacets.connectView(dynamicFacetListView)
        searcher.query.facets = setOf(brand, color, size, country)
        searcher.searchAsync()
    }

    override fun onDestroy() {
        super.onDestroy()
        searcher.cancel()
        connection.clear()
    }
}

Customizing your view

InstantSearch Android provides DynamicFacetListView interface, it’s the view presenting the ordered list of facets and handling user interaction.

You can provide your implementation of DynamicFacetListView interface:

1
2
val myDynamicFacetListView = MyDynamicFacetListView() // your implementation `DynamicFacetListView`
dynamicFacets.connectView(myDynamicFacetListView)

Android view

InstantSearch Android provides DynamicFacetListAdapter, an opinionated implementation of DynamicFacetListView interface and a subclass of ListAdapter class. Provide your implementation of DynamicFacetListViewHolder.Factory interface to your DynamicFacetListAdapter:

1
2
3
val factory = DynamicFacetListViewHolderImpl.Factory // your implementation of `DynamicFacetListViewHolder.Factory`
val dynamicFacetListView = DynamicFacetListAdapter(factory)
dynamicFacets.connectView(dynamicFacetListView)

Compose UI

InstantSearch Android provides the DynamicFacetListState, an implementation of the DynamicFacetListView interface adapted for usage with Compose UI. It provides facetOrder and facetSelections properties with convenient toggle and isSelected functions which allow you to implement your own Compose UI view.

Implementation example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Composable
fun DynamicFacetsList(modifier: Modifier = Modifier, dynamicFacetListState: DynamicFacetListState) {
    LazyColumn(modifier) {
        dynamicFacetListState.facetOrder.forEach { (attribute, facets) ->
            item {
                Header(attribute = attribute)
            }
            items(facets) { facet ->
                FacetRow(
                    modifier = Modifier.fillMaxWidth(),
                    facet = facet,
                    isSelected = dynamicFacetListState.isSelected(facet, attribute),
                    onClick = { dynamicFacetListState.toggle(facet, attribute) }
                )
            }
        }
    }
}

@Composable
fun Header(modifier: Modifier = Modifier, attribute: Attribute) {
    Text(modifier = modifier.padding(horizontal = 16.dp, vertical = 8.dp), text = attribute.raw)
}

@Composable
fun FacetRow(modifier: Modifier = Modifier, facet: Facet, isSelected: Boolean,onClick: () -> Unit = {}) {
    Card(modifier = modifier, onClick = onClick) {
        Row(Modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
            Text(modifier = Modifier.weight(1f), text = facet.value)
            if (isSelected) Icon(Icons.Default.Check, contentDescription = null)
            Text(text = facet.count.toString())
        }
    }
}

Did you find this page helpful?