Searching & Filtering
Large sets of data should usually support search.
On this page
Overview
HQ has a custom searching and filtering component that uses Knockout Components. See search_box.js for full documentation.
Usage
The best way to understand how to implement the search box widget is to see its use in HQ directly. The best sources for this are the Web Users and Mobile Workers pages. As you might notice, it's often the case that the search box component is used in combination with the pagination component.
For the Mobile Workers page, the key points are:
- the HTML widget initializing the search box
- the goToPage javascript function that passes the query to the server (along with pagination data)
- the django view that uses the query value along with other pagination information to return the list of mobile workers
A Quick Example
Here is a quick example simulating the search box usage. Ideally, this searching should be done asynchronously, as this widget is most useful for larger data sets, and it would likely be inefficient store the whole dataset in memory. This is mainly to have a visual reference of the search box widget.
immediate
parameter used in this example controls whether the widget searches on every key press or only when
the user clicks the search button or presses enter.
<div id="js-search-box-example"> <search-box data-apply-bindings="false" params=" value: query, action: search, immediate: true, placeholder: 'Search...' " ></search-box> <ul class="list-group pt-3" data-bind="foreach: items" > <li class="list-group-item" data-bind="text: $data" ></li> </ul> </div>
import $ from 'jquery'; import ko from 'knockout'; import _ from 'underscore'; import 'hqwebapp/js/components/search_box'; var searchBoxExample = function () { var self = {}; self.allItems = "alpha beta delta gamma epsilon omega chi".split(" "); self.items = ko.observableArray(self.allItems); self.query = ko.observable(''); self.search = function (page) { // eslint-disable-line no-unused-vars self.items(_.filter(self.allItems, function (item) { return item.indexOf(self.query()) !== -1; })); }; return self; }; $("#js-search-box-example").koApplyBindings(searchBoxExample());
Client-Side Only Search
In some cases we might only want to do client-side searches. This means that the entire data set is stored in browser memory, and we query that dataset without making additional calls to the server.
An example use case for this is the "Clean Case Data" modal that can be accessed from the Case Data page. In this page we use the search box widget to filter case properties.
Key points for this example are:
- the search box widget
- the javascript code that applies the query to the list of case properties
search-box
widget usage only. The UI for this feature as a whole
should not be duplicated as a "best practice" and hopefully cleaned up in the future.