UI libraries / Algolia for Flutter / Widgets
Signature
HitsSearcher(
  String applicationID,
  String apiKey,
  String indexName,
  // Optional parameters
  bool disjunctiveFacetingEnabled,
  Duration debounce,
)

HitsSearcher.create(
  String applicationID,
  String apiKey,
  SearchState state,
  // Optional parameters
  bool disjunctiveFacetingEnabled,
  Duration debounce,
)

About this widget

This component is the main entry point for Flutter Helpers: it handles search requests and manages search sessions.

HitsSearcher component has the following behavior:

  • Distinct state changes (including initial state) will trigger a search operation
  • State changes are debounced
  • On a new search request, any previous ongoing search calls will be cancelled

Examples

  1. Create a HitsSearcher
  2. Update search state with query and applyState
  3. Listen to search responses and build the UI
  4. dispose of underlying resources
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
54
55
class SearchScreen extends StatefulWidget {
  const SearchScreen({super.key});

  @override
  State<SearchScreen> createState() => _SearchScreenState();
}

class _SearchScreenState extends State<SearchScreen> {
  // 1. Create a Hits Searcher
  final hitsSearcher = HitsSearcher(
    applicationID: 'YourApplicationID',
    apiKey: 'YourSearchOnlyApiKey',
    indexName: 'YourIndexName',
  );

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          // 2. Run your search operations
          title: TextField(
            onChanged: (input) => hitsSearcher.query(input),
            decoration: const InputDecoration(
              hintText: 'Search...',
              prefixIcon: Icon(Icons.search),
              fillColor: Colors.white,
              filled: true,
            ),
          ),
        ),
        // 3.1 Listen to search responses
        body: StreamBuilder<SearchResponse>(
          stream: hitsSearcher.responses,
          builder: (_, snapshot) {
            if (snapshot.hasData) {
              final response = snapshot.data;
              final hits = response?.hits.toList() ?? [];
              // 3.2 Display your search hits
              return ListView.builder(
                itemCount: hits.length,
                itemBuilder: (_, i) => ListTile(title: Text(hits[i]['title'])),
              );
            } else {
              return const Center(child: CircularProgressIndicator());
            }
          },
        ),
      );

  @override
  void dispose() {
    super.dispose();
    // 4. Release underling resources
    hitsSearcher.dispose();
  }
}

Parameters

applicationID
type: String
Required

The ID of your application.

1
2
3
4
5
final hitsSearcher = HitsSearcher(
  applicationID: 'YourApplicationID',
  apiKey: 'YourSearchOnlyApiKey',
  indexName: 'YourIndexName',
);
apiKey
type: String
Required

Your application’s Search-only API key.

1
2
3
4
5
final hitsSearcher = HitsSearcher(
  applicationID: 'YourApplicationID',
  apiKey: 'YourSearchOnlyApiKey',
  indexName: 'YourIndexName',
);
indexName
type: String
Required

The index to search into.

1
2
3
4
5
final hitsSearcher = HitsSearcher(
  applicationID: 'YourApplicationID',
  apiKey: 'YourSearchOnlyApiKey',
  indexName: 'YourIndexName',
);
state
type: SearchState
Required

Initial search state.

1
2
3
4
5
final hitsSearcher = HitsSearcher.create(
  applicationID: 'YourApplicationID',
  apiKey: 'YourSearchOnlyApiKey',
  state: const SearchState(indexName: 'YourIndexName'),
);
disjunctiveFacetingEnabled
type: bool
default: true
Optional

Is disjunctive faceting enabled?

1
2
3
4
5
6
final hitsSearcher = HitsSearcher(
  applicationID: 'YourApplicationID',
  apiKey: 'YourSearchOnlyApiKey',
  indexName: 'YourIndexName',
  disjunctiveFacetingEnabled: true,
);
debounce
type: Duration
default: Duration(milliseconds: 100)
Optional

Search operation debounce duration.

1
2
3
4
5
6
final hitsSearcher = HitsSearcher(
  applicationID: 'YourApplicationID',
  apiKey: 'YourSearchOnlyApiKey',
  indexName: 'YourIndexName',
  debounce: const Duration(milliseconds: 100),
);

Fields

responses
type: Stream<SearchResponse>

Stream of search responses

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
StreamBuilder<SearchResponse>(
  stream: hitsSearcher.responses,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      final response = snapshot.data!;
      return Column(
        children: [
          Text('${response.nbHits} hits found'),
          ListView.builder(
            itemCount: response.hits.length,
            itemBuilder: (context, index) {
              final hit = response.hits[index];
              return ListTile(title: Text(hit['name']));
            },
          ),
        ],
      );
    } else {
      return const CircularProgressIndicator();
    }
  },
);
state
type: Stream<SearchState>

Stream of search states

1
2
3
4
5
6
7
8
9
10
11
StreamBuilder<SearchState>(
  stream: searcher.state,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      final query = snapshot.data?.query ?? '';
      return Text('Query: $query');
    } else {
      return const CircularProgressIndicator();
    }
  },
);

Methods

query

Triggers a search operation with given search query

1
hitsSearcher.query('book');
applyState

Applies a search state configuration and triggers a search operation

1
hitsSearcher.applyState((state) => state.copyWith(query: 'book', page: 0));
snapshot

Gets the latest SearchResponse value submitted by responses stream:

1
final response = hitsSearcher.snapshot();
dispose

Releases all underlying resources

1
hitsSearcher.dispose();
Did you find this page helpful?