> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dynamic Facets

> Shows ordered facets and facet values based on index settings and rules.

```kotlin Signature theme={"system"}
DynamicFacetListConnector(
    searcher: SearcherIndex,
    filterState: FilterState,
    orderedFacets: List<AttributedFacets>,
    selections: SelectionsPerAttribute,
    selectionModeForAttribute: Map<String, SelectionMode>,
    filterGroupForAttribute: Map<String, FilterGroupDescriptor>
)
```

<Card title="Explore example code" icon="github" href="https://github.com/algolia/instantsearch-android/tree/master/examples/android">
  Browse the Dynamic Facets example code on GitHub.
</Card>

## 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 is defined by the corresponding index settings and applied index rules.
You can configure the facet merchandising through the corresponding index setting.
To learn more, see [Facet display](/doc/guides/building-search-ui/ui-and-ux-patterns/facet-display/android).

### Requirements

You must set the attributes for faceting and configure the facet order, either using the [dashboard](/doc/guides/managing-results/refine-results/faceting/how-to/declaring-attributes-for-faceting-with-dashboard) or with the API parameters [`attributesForFaceting`](/doc/api-reference/api-parameters/attributesForFaceting) and [`renderingContent`](/doc/api-reference/api-parameters/renderingContent).

You must also set the [`facets`](/doc/api-reference/api-parameters/facets) property of the query with `Searcher.indexQueryState.query.facets` and provide the facet attributes you want to retrieve.

<Note>
  You must use InstantSearch Android v2.11 or later to use `DynamicFacets`.
</Note>

## Examples

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

```kotlin Kotlin icon=code theme={"system"}
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = "YourApplicationID",
        apiKey = "YourSearchOnlyAPIKey",
        indexName = "YourIndexName"
    )
    val filterState = FilterState()
    val color = "color"
    val country = "country"
    val brand = "brand"
    val size = "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 = searcher.query.copy(facets = listOf(brand, color, size, country))
        searcher.searchAsync()
    }

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

## Parameters

<ResponseField name="searcher" type="SearcherIndex" required>
  The [`Searcher`](/doc/api-reference/widgets/instantsearch/android) that handles your searches.
</ResponseField>

<ResponseField name="filterState" type="FilterState" required>
  The [`FilterState`](/doc/api-reference/widgets/filter-state/android) that holds your filters.
</ResponseField>

<ResponseField name="orderedFacets" type="List<AttributedFacets>" post={["default: []"]}>
  The ordered list of attributed facets.
</ResponseField>

<ResponseField name="selections" type="SelectionsPerAttribute" post={["default: []"]}>
  The mapping between a facet attribute and a set of selected facet values.
</ResponseField>

<ResponseField name="selectionModeForAttribute" type="Map<String, SelectionMode>" post={["default: [:]"]}>
  The mapping between a facet attribute and a facet values selection mode. If not provided, the default selection mode is `Single`.
</ResponseField>

<ResponseField name="filterGroupForAttribute" type="Map<String, FilterGroupDescriptor>" post={["default: [:]"]}>
  The mapping between a facet attribute and a descriptor of a filter group where the corresponding facet filters are stored in the filter state.
</ResponseField>

## View

<ParamField body="view" type="DynamicFacetListView" required>
  The view that render the dynamic facets list.

  ```kotlin Kotlin icon=code theme={"system"}
  val facetListAdapter = FacetListAdapter(FacetListViewHolderImpl.Factory)
  val facetListPresenter = FacetListPresenterImpl(listOf(FacetSortCriterion.CountDescending, FacetSortCriterion.AlphabeticalAscending))
  facetListCategory.connectView(facetListAdapter, facetListPresenter)
  ```
</ParamField>

## 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`](/doc/api-reference/widgets/instantsearch/android) that handles your searches.
* `FilterState`: the current state of the filters.
* `DynamicFacetsListViewModel`: dynamic facets business logic

```kotlin Kotlin icon=code theme={"system"}
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = "YourApplicationID",
        apiKey = "YourSearchOnlyAPIKey",
        indexName = "YourIndexName"
    )
    val filterState = FilterState()
    val color = "color"
    val country = "country"
    val brand = "brand"
    val size = "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 = searcher.query.copy(facets = listOf(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:

```kotlin Kotlin icon=code theme={"system"}
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`:

```kotlin Kotlin icon=code theme={"system"}
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 let you implement your own Compose UI view.

#### Implementation example

```kotlin Kotlin icon=code theme={"system"}
import com.algolia.client.model.search.FacetHits

@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: String) {
    Text(modifier = modifier.padding(horizontal = 16.dp, vertical = 8.dp), text = attribute)
}

@Composable
fun FacetRow(modifier: Modifier = Modifier, facet: FacetHits, 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())
        }
    }
}
```
