fabio
fabio

Reputation: 466

Flutter Autocomplete widget delays updating suggestions

I'm facing a problem using the Autocomplete widget. Basically, the list of options that shows up while I'm typing in the text field is delayed by one character.

For example, let's say a set of data like ["Apple", "Banana", "Orange"]. If the text field is initially empty and I start typing the letter 'A', nothing happens. Then I type for example the letter 'k', so that there shouldn't be any match with data, but the widget displays "Apple" in the options list. Then let's say I remove the last letter, 'k', so that there is only the 'A' and there should be a match with the word "Apple", but the widget doesn't display anything. And so on.

Autocomplete<Song>(
      optionsBuilder: (_) => state.searchResults,
      fieldViewBuilder: (context, controller, focusNode, onFieldSubmitted) {
        return TextField(
          controller: controller,
          focusNode: focusNode,
          onChanged: (value) {
            context.read(searchProvider.notifier).inputChanged(value);
          },
        );
      },
      optionsViewBuilder: (context, onSelected, options) {
        return Align(
          alignment: Alignment.topLeft,
          child: Material(
            child: SizedBox(
              height: 100.0,
              child: ListView(
                padding: EdgeInsets.all(kDefaultPadding / 3),
                itemExtent: 40.0,
                children: options
                    .map(
                      (song) => SuggestionEntry(song: song),
                    )
                    .toList(),
              ),
            ),
          ),
        );
      },
    )

I'm using Riverpod as state manager, but it shouldn't be the problem since I'm using the same StateNotifier also in other parts of the page which are updated correctly. Also, note that the list of suggestions stored in the StateNotifier is correctly based on the current input, so it seems that the problem is during the "rendering" of the Autocomplete widget.

Example: https://drive.google.com/file/d/17FZuxgDoHhOR2ceAUsOtADZZe23BU0m1/view?usp=sharing

Upvotes: 1

Views: 1524

Answers (2)

Dastan Kerimkulov
Dastan Kerimkulov

Reputation: 1

Instead of options, you need to pass state.searchResults

Autocomplete<Song>(
      optionsBuilder: (_) => state.searchResults,
      fieldViewBuilder: (context, controller, focusNode, onFieldSubmitted) {
        return TextField(
          controller: controller,
          focusNode: focusNode,
          onChanged: (value) {
            context.read(searchProvider.notifier).inputChanged(value);
          },
        );
      },
      optionsViewBuilder: (context, onSelected, options) {
        return Align(
          alignment: Alignment.topLeft,
          child: Material(
            child: SizedBox(
              height: 100.0,
              child: ListView(
                padding: EdgeInsets.all(kDefaultPadding / 3),
                itemExtent: 40.0,
                children: state.searchResults
                    .map(
                      (song) => SuggestionEntry(song: song),
                    )
                    .toList(),
              ),
            ),
          ),
        );
      },
    )
    ```

Upvotes: 0

ghchoi
ghchoi

Reputation: 5156

optionsBuilder is called before fieldViewBuilder.onChange. So remove the part

onChanged: (value) {
    context.read(searchProvider.notifier).inputChanged(value);
},

and move the definition to inside optionsBuilder like:

optionsBuilder: (TextEditingValue value) {
    await context.read(searchProvider.notifier).inputChanged(value);
    return ...;
},

Upvotes: 2

Related Questions