Flutter: My search input text does not query Algolia database

I am working on a real estate app where I would like to display a list of properties, that is retrieved from the Algolia database, and search them from the search input field by typing the I.D of the properties. Like this

I have successfully linked/setup Firebase & Algolia. And I am able to display the properties on the screen, using infinite_scroll_pagination and algolia_helper_flutter packages.

The problem I am facing is I cannot search the houses by typing the I.D of the properties.

Please check out my code, tell me where I went wrong. Thank you.

Best,

class HousesListView extends StatefulWidget {
  const HousesListView({Key? key}) : super(key: key);

  @override
  State<HousesListView> createState() => _HousesListViewState();
}

class _HousesListViewState extends State<HousesListView> {
  // textController for search box input
  final _searchTextController = TextEditingController();

  // pageController from infinite_scroll_pagination package
  final PagingController<int, MdlAlgoliaProperties> pagingController =
      PagingController(firstPageKey: 0);

  /// Component holding search filters from algolia_helper_flutter package
  final _filterState = FilterState();

  // search houses in Algolia Database
  final _houseDatabase = HitsSearcher.create(
      applicationID: AlgoliaCredentials.applicationID,
      apiKey: AlgoliaCredentials.apiKey,
      state: const SearchState(
          indexName: AlgoliaCredentials.hitsIndex,
          facetFilters: ['a2-propertyType: House']));

  // stream and display list of properties on the screen
  Stream<PropertiesPage> get displayPropertiesOnThePage =>
      _houseDatabase.responses.map(PropertiesPage.fromResponse);

  /// Get stream of search result, like the number of the result from the search box
  Stream<SearchMetadata> get searchMetadata =>
      _houseDatabase.responses.map(SearchMetadata.fromResponse);

  @override
  void initState() {
    super.initState();

    // listen to keystroke & query the results by the letters that user types in
    _searchTextController
        .addListener(() => _houseDatabase.query(_searchTextController.text));

    // load properties on the page
    displayPropertiesOnThePage.listen((properties) {
      if (properties.pageKey == 0) pagingController.refresh();
      pagingController.appendPage(
          properties.alogliaPPT, properties.nextPageKey);
    }).onError((error) => pagingController.error = error);

    // error here!
    // this loads the list of house successfully and properly when its enabled, but search does not work anymore
    // but, when this disable, the search works, but it does not load the list of houses anymore
    pagingController.addPageRequestListener((pageKey) =>
        _houseDatabase.applyState((state) => state.copyWith(page: pageKey))); //<= error occur in this line

    // connect database and filter state
    _houseDatabase.connectFilterState(_filterState);

    // pageController listens to filterState
    _filterState.filters.listen((_) => pagingController.refresh());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: appBarTitle(context, 'List of Houses'),
      backgroundColor: ZayyanColorTheme.zayyanGrey,
      endDrawer: const Drawer(
        width: 350,
        child: HouseFilter(),
      ),
      body: Center(
        child: Column(
          children: [
            SizedBox(
              height: 44,
              child: TextField(
                controller: _searchTextController,
                decoration: const InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term',
                  prefixIcon: Icon(Icons.search),
                ),
              ),
            ),
            StreamBuilder<SearchMetadata>(
              stream: searchMetadata,
              builder: (context, snapshot) {
                if (!snapshot.hasData) {
                  return const SizedBox.shrink();
                }
                return Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text('${snapshot.data!.nbHits} hits'),
                );
              },
            ),
            Expanded(
              child: _hits(context),
            ),
          ],
        ),
      ),
    );
  }

  Widget _hits(BuildContext context) {
    return PropertyHitsListView(
      pagingController: pagingController,
      noItemsFound: (context) => const NoResultsView(),
      onHitClick: (objectID) {
        print(objectID);
      },
    );
  }

  @override
  void dispose() {
    _searchTextController.dispose();
    _houseDatabase.dispose();
    _filterState.dispose();
    pagingController.dispose();
    super.dispose();
  }
}

Hi @thawah.ryan

I’m not a Flutter expert, but your code seems to match well with our Flutter Helper setup. I’m wondering if this is an index configuration issue.

Can you confim the ID is a searchable attribute for the index? Also, Algolia is by default configured in an opinionated way for prefix text search, so you often need to tweak some settings to search in IDs or SKUs, particularly if you’re trying to search in the middle of the ID.

There are some good tips in this guide about searching by SKU:

You may also need to disablePrefixOnAttributes to do the middle search:

Finally, this guide has some tips for handling hyphenated values like you show in your screenshot:

I think with those three guides you should get what you need for ID search.