Skip to main content
Signature
HierarchicalConnector(
    searcher: HitsSearcher,
    attribute: Attribute,
    filterState: FilterState,
    hierarchicalAttributes: List<Attribute>,
    separator: String
)

About this widget

A Hierarchical Menu is a component that displays a hierarchical navigation menu, based on facet attributes.

Examples

Kotlin
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val hierarchicalCategory = Attribute("categories")
    val hierarchicalCategoryLvl0 = Attribute("$categories.lvl0")
    val hierarchicalCategoryLvl1 = Attribute("$categories.lvl1")
    val hierarchicalCategoryLvl2 = Attribute("$categories.lvl2")
    val hierarchicalAttributes = listOf(
        hierarchicalCategoryLvl0,
        hierarchicalCategoryLvl1,
        hierarchicalCategoryLvl2
    )
    val filterState = FilterState()
    val separator = " > "
    val hierarchical = HierarchicalConnector(
        searcher = searcher,
        attribute = hierarchicalCategory,
        filterState = filterState,
        hierarchicalAttributes = hierarchicalAttributes,
        separator = separator
    )
    val connection = ConnectionHandler(hierarchical, searcher.connectFilterState(filterState))

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val view : HierarchicalView = HierarchicalAdapter() // your HierarchicalView implementation
        connection += hierarchical.connectView(view, HierarchicalPresenterImpl(separator))
        searcher.searchAsync()
    }

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

Low-level API

If you want to fully control the Hierarchical Menu components and connect them manually, use the following components:
  • Searcher. The Searcher that handles your searches.
  • FilterState. The current state of the filters.
  • HierarchicalViewModel. The logic applied to the hierarchical facets.
  • HierarchicalView. The concrete hierarchical view.
  • HierarchicalPresenter. The presenter that controls the sorting and other settings of the hierarchical menu.
  • HierarchicalItem. A single node in the hierarchy.
Kotlin
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val filterState = FilterState()

    val hierarchicalCategory = Attribute("categories")
    val hierarchicalCategoryLvl0 = Attribute("$categories.lvl0")
    val hierarchicalCategoryLvl1 = Attribute("$categories.lvl1")
    val hierarchicalCategoryLvl2 = Attribute("$categories.lvl2")
    val hierarchicalAttributes = listOf(
        hierarchicalCategoryLvl0,
        hierarchicalCategoryLvl1,
        hierarchicalCategoryLvl2
    )
    val separator = " > "
    val viewModel = HierarchicalViewModel(hierarchicalCategory, hierarchicalAttributes, separator)
    val connection = ConnectionHandler()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val view: HierarchicalView = HierarchicalAdapter() // your `HierarchicalView` implementation

        connection += searcher.connectFilterState(filterState)
        connection += viewModel.connectFilterState(filterState)
        connection += viewModel.connectSearcher(searcher)
        connection += viewModel.connectView(view, HierarchicalPresenterImpl(separator))

        searcher.searchAsync()
    }

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

Compose UI

InstantSearch provides HierarchicalState as a state model, which implements the HierarchicalView interface. You need to connect HierarchicalState to the HierarchicalConnector or HierarchicalViewModel like any other HierarchicalView implementation.
Kotlin
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val hierarchicalCategory = Attribute("categories")
    val hierarchicalCategoryLvl0 = Attribute("$categories.lvl0")
    val hierarchicalCategoryLvl1 = Attribute("$categories.lvl1")
    val hierarchicalCategoryLvl2 = Attribute("$categories.lvl2")
    val hierarchicalAttributes = listOf(
        hierarchicalCategoryLvl0,
        hierarchicalCategoryLvl1,
        hierarchicalCategoryLvl2
    )
    val filterState = FilterState()
    val separator = " > "
    val hierarchicalState = HierarchicalState()
    val hierarchical = HierarchicalConnector(
        searcher = searcher,
        attribute = hierarchicalCategory,
        filterState = filterState,
        hierarchicalAttributes = hierarchicalAttributes,
        separator = separator
    )
    val connections = ConnectionHandler(hierarchical)

    init {
        connections += searcher.connectFilterState(filterState)
        connections += hierarchical.connectView(hierarchicalState, HierarchicalPresenterImpl(separator))
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            LazyColumn {
                items(hierarchicalState.hierarchicalItems) { item ->
                    HierarchicalItem( // your own UI composable to display `HierarchicalItem`
                        item = item,
                        onClick = { hierarchicalState.onSelectionChanged?.invoke(item.facet.value) }
                    )
                }
            }
        }
        searcher.searchAsync()
    }

    override fun onDestroy() {
        super.onDestroy()
        connections.disconnect()
        searcher.cancel()
    }
}

Parameters

searcher
HitsSearcher
required
The Searcher that handles your searches.
attribute
Attribute
required
The attribute to filter.
filterState
FilterState
required
The FilterState that holds your filters.
hierarchicalAttributes
List<Attribute>
required
The names of the hierarchical attributes that you need to target, in ascending order.
separator
String
required
The delimiter used to separate hierarchical facets. Usually something like ” > ”, including spaces as shown in this example.

View

view
HierarchicalView
required
The view that renders the hierarchical menu.
presenter
HierarchicalPresenter
required
How to display the list of HierarchicalItem. Takes a list of HierarchicalItem and returns a new list of HierarchicalItem. A HierarchicalItem contains a Facet, its level, and a displayName.
Kotlin
val view: HierarchicalView = HierarchicalAdapter()
val separator = " > "
val presenter = HierarchicalPresenterImpl(separator)
hierarchical.connectView(view, presenter)

// Example of `HierarchicalView` implementation
class HierarchicalAdapter : HierarchicalView,
    ListAdapter<HierarchicalItem, HierarchicalViewHolder>(DiffUtilItem()) {
    override var onSelectionChanged: Callback<String>? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HierarchicalViewHolder {
        return HierarchicalViewHolder(parent.inflate(R.layout.list_item_selectable, false))
    }

    override fun onBindViewHolder(holder: HierarchicalViewHolder, position: Int) {
        val item = getItem(position)
        holder.bind(item) { onSelectionChanged?.invoke(item.facet.value) }
    }

    override fun setTree(tree: List<HierarchicalItem>) {
        submitList(tree)
    }
}

class DiffUtilItem<T : Filter> : DiffUtil.ItemCallback<SelectableItem<T>>() {
    override fun areItemsTheSame(oldItem: SelectableItem<T>, newItem: SelectableItem<T>): Boolean {
        return oldItem.first == newItem.first
    }

    override fun areContentsTheSame(oldItem: SelectableItem<T>, newItem: SelectableItem<T>): Boolean {
        return oldItem == newItem
    }
}
I