Hierarchical Menu
About this widget
Hierarchical Menu is a filtering view that displays a hierarchy of facets that let your user refine their search results.
To add a hierarchical menu to your search experience, use these components:
Searcher
: TheSearcher
that handles your searches.FilterState
: The current state of the filters.HierarchicalInteractor
: The logic applied to the hierarchical facets.HierarchicalController
: The controller that interfaces with a concrete hierarchical facet list view.HierarchicalPresenter
: Optional. The presenter that controls the sorting and other settings of the refinement facet list view.
Examples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Note: They need to be in order or else we'll get a wrong behavior.
let hierarchicalAttributes = [
Attribute("hierarchicalCategories.lvl0"),
Attribute("hierarchicalCategories.lvl1"),
Attribute("hierarchicalCategories.lvl2"),
]
let searcher: SingleIndexSearcher = .init(...)
let filterState: FilterState = .init()
let hierarchicalInteractor: HierarchicalInteractor = { return .init(hierarchicalAttributes: hierarchicalAttributes, separator: " > ") }()
let hierarchicalTableViewController: HierarchicalTableViewController = .init(tableView: UITableView())
override func viewDidLoad() {
super.viewDidLoad()
searcher.connectFilterState(filterState)
hierarchicalInteractor.connectSearcher(searcher: searcher)
hierarchicalInteractor.connectFilterState(filterState)
hierarchicalInteractor.connectController(hierarchicalTableViewController)
searcher.search()
}
Parameters
hierarchicalAttributes
|
type: [Attribute]
Required
The names of the hierarchical attributes that we need to target, in ascending order. |
||
Copy
|
|||
separator
|
type: String
Required
The string separating the facets in the hierarchical facets. Usually something like “ > “. Note that you should not forget the spaces in between if there are some in your separator. |
||
Copy
|
Presenter
Hierarchical Presenter
|
type: (([HierarchicalFacet]) -> [HierarchicalFacet])?
default: nil
Optional
The presenter that defines the way we want to display the list of Takes a list of A Hierarchical Facet is a tuple of a |
||
Copy
|
Customize your view
The controllers provided by default, like the HierarchicalTableViewController
work well when you want to use native UIKit with their default behavior.
If you want to use another component such as a UICollectionView
, a third-party input view, or you want to introduce some custom behavior to the already provided UIKit component, you can create your own controller conforming to the HierarchicalController
protocol.
Protocol
var onClick: ((String) -> Void)?
:
Closure to call when a new hierarchical facet is clicked.
func setItem(_ item: [HierarchicalFacet])
Function called when a new array of hierarchical facets is updated. This is the UI State of the refinement list. Make sure to reload your view here when you get the new items.
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
open class HierarchicalTableViewController: NSObject, HierarchicalController {
public var onClick: ((String) -> Void)?
var items: [HierarchicalFacet]
var tableView: UITableView
let cellID: String
public init(tableView: UITableView, cellID: String = "HierarchicalFacet") {
self.tableView = tableView
self.items = []
self.cellID = cellID
super.init()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)
tableView.dataSource = self
tableView.delegate = self
}
public func setItem(_ item: [HierarchicalFacet]) {
self.items = item
tableView.reloadData()
}
}
extension HierarchicalTableViewController: UITableViewDataSource {
open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath)
let maxSelectedLevel = Set(items.filter { $0.isSelected }.map { $0.level }).max() ?? 0
let item = items[indexPath.row]
cell.textLabel?.text = "\(item.facet.description)"
cell.indentationLevel = item.level
cell.accessoryType = item.level == maxSelectedLevel && item.isSelected ? .checkmark : .none
return cell
}
}
extension HierarchicalTableViewController: UITableViewDelegate {
open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = items[indexPath.row]
onClick?(item.facet.value)
}
}