Reputation: 466
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
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
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