0

I'm trying to have a ListView dynamically update depending on the contents of a TextField (a search bar).

The ListView is inside a "ScenariosList" widget, and contains a list of "Scenarios", which is a custom widget containing a title, content and other bits of data (not really relevant but helpful for context). It's content is fetched from a database via a "ScenariosBloc".

The TextField is contained within a "SearchBar" widget.

The goal is to have the contents of the ListView change whenever a change to the TextField is detected.

I'm currently using two individual blocs. ScenariosBloc fetches all the scenarios from the database and FilterScenariosBloc makes the List render a widget to show the scenario if it's title contains the string in the TextView within the SearchBar.

I'm using nested StreamBuilders to do this (see code below).

ScenariosList.dart

  // build individual scenario cards
  Widget _buildScenarioListItem(Scenario scen, String filter) {
    if (!(filter == null || filter == "")) {
      print("null filter");
      if (!(scen.title.contains(filter))) {
        print("match!");
        return ScenarioCard(scen);
      }
    }
    return Container();
  }

  Widget _buildScenarioList(BuildContext context) {
    return StreamBuilder(
        stream: scenarioBloc.scenarios,
        builder: (BuildContext context,
            AsyncSnapshot<List<Scenario>> scenariosSnapshot) {
          if (!scenariosSnapshot.hasData) {
            return CircularProgressIndicator();
          }
          return StreamBuilder(
              stream: filterScenariosBloc.filterQuery,
              initialData: "",
              builder: (BuildContext context, AsyncSnapshot filterSnapshot) {

                if(!filterSnapshot.hasData) return CircularProgressIndicator();

                print("Scenarios Snapshot: ${scenariosSnapshot.toString()}");
                print("Filter Snapshot: ${filterSnapshot.toString()}");

                return ListView.builder(
                  physics: NeverScrollableScrollPhysics(),
                  padding: EdgeInsets.all(0),
                  shrinkWrap: true,
                  itemCount: scenariosSnapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                    Scenario scen = scenariosSnapshot.data[index];
                    return _buildScenarioListItem(scen, filterSnapshot.data);
                  },
                );
              });
        });
  }

}

SearchBar.dart

the onChanged method of the Textfield contains:

    // function to filter the scenarios depending on the users input.
    void filterSearchResults(String query) {
      _filterScenariosBloc.doFilter(query);
    }

FilterScenariosBloc.dart

class FilterScenariosBloc {
  // stream - only need one listener
  final _searchController = StreamController<String>.broadcast();

  // output stream
  get filterQuery => _searchController.stream;

  FilterScenariosBloc() {
    doFilter(" ");
  }

  doFilter(String query) {
    _searchController.sink.add(query);
  }
}

The user input is sent to the FilterScenariosBloc all fine, but the status of the filterSnapshot is always connectionState.waiting. Any ideas on how I can resolve this?

Tom Milner
  • 1
  • 1
  • 2
  • I had tried to build my own custom search but it proved a bit of a headache, I ended up just following this tutorial https://medium.com/flutterpub/a-simple-search-bar-in-flutter-f99aed68f523 . Remember to convert your item string and query both to lowercase. Here is another BLOC specific one https://medium.com/flutterpub/implementing-search-in-flutter-17dc5aa72018 – F-1 Jul 05 '19 at 10:14

2 Answers2

1

I had the same issue. The problem was that my firestore DB rules did not allow read or write for the collection in question. Please see if that solves your prob

Speedy11
  • 197
  • 1
  • 5
  • 11
-3

I had the same issue, always having the connectionState.waiting, and thus the snapshot.data was null. This means that for whatever reason, the data could not be fetched. I then ran the app into the debug mode and got an error like "Cannot fit requested classes into a single dex file". Then I just followed this answer and it solved the issue for me.

BogdanP
  • 1
  • 3