Reputation: 11
I'm trying to build a search bar where the user can look up for a place, and select a suggestion corresponding on what caracters they wrote. I'm using BLOC, and an API to fetch the suggestions from the string the user wrote. The widget that I use to display the suggestion is 'Autocomplete'. My problem is that this Autocompletion widget doesn't rebuild the suggestions, while the blocbuilder (parent of 'Autocompletion') is properly rebuilt.
My bloc to fetch the suggestions has 3 states: Error, PlaceSuggestionsLoading and PlaceSuggestionLoaded, and work fine.
This is what I've tried:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class Place {
final String name;
Place({required this.name});
}
abstract class PlaceResearchState {}
class PlaceResearchInitial extends PlaceResearchState {}
class PlaceSuggestionsLoading extends PlaceResearchState {}
class PlaceSuggestionsLoaded extends PlaceResearchState {
final List<Place> placeSuggestions;
PlaceSuggestionsLoaded(this.placeSuggestions);
}
class PlaceSuggestionsError extends PlaceResearchState {
final String message;
PlaceSuggestionsError(this.message);
}
class PlaceResearchBloc extends Cubit<PlaceResearchState> {
PlaceResearchBloc() : super(PlaceResearchInitial());
void searchSuggestions(String query) {
if (query.isEmpty) {
emit(PlaceResearchInitial());
return;
}
emit(PlaceSuggestionsLoading());
Future.delayed(Duration(milliseconds: 500), () {
final suggestions = _fetchPlaceSuggestions(query);
if (suggestions.isNotEmpty) {
emit(PlaceSuggestionsLoaded(suggestions));
} else {
emit(PlaceSuggestionsError("No suggestion found"));
}
});
}
List<Place> _fetchPlaceSuggestions(String query) {
List<Place> allPlaces = [
Place(name: 'New York'),
Place(name: 'Paris'),
Place(name: 'London'),
Place(name: 'Hamburg'),
Place(name: 'Barcelona')
];
return allPlaces.where((place) => place.name.toLowerCase().contains(query.toLowerCase())).toList();
}
}
class SearchBarWithBlocListener extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Autocomplete MRE")),
body: Stack(
children: [
Positioned(
top: 20,
left: 10,
right: 10,
child: Material(
elevation: 4,
borderRadius: BorderRadius.circular(8),
child: BlocProvider(
create: (_) => PlaceResearchBloc(),
child: BlocBuilder<PlaceResearchBloc, PlaceResearchState>(
builder: (context, state) {
List<String> suggestions = [];
if (state is PlaceSuggestionsLoaded) {
suggestions = state.placeSuggestions.map((place) => place.name).toList();
}
print("Bloc builder Suggestions : $suggestions");
return Autocomplete<String>(
optionsBuilder: (TextEditingValue textEditingValue) {
print("Autocomplete suggestions : $suggestions");
return suggestions.where(
(suggestion) => suggestion.toLowerCase().contains(textEditingValue.text.toLowerCase()),
);
},
displayStringForOption: (String option) => option,
onSelected: (String selection) {
print('Selected suggestion : $selection');
},
fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
return TextField(
controller: fieldTextEditingController,
focusNode: fieldFocusNode,
onChanged: (value) {
// Search for suggestions on each modifications
context.read<PlaceResearchBloc>().searchSuggestions(value);
},
decoration: InputDecoration(
hintText: "Search for a place",
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(horizontal: 15, vertical: 10),
),
);
},
);
},
),
),
),
),
],
),
);
}
}
What I don't undestand is that the first print
:
print("Bloc builder Suggestions : $suggestions");
is triggered when I get the new suggestions to show, but not the second one:
print("Autocomplete suggestions : $suggestions");
and so the suggestions are not updated when they are loaded by the bloc.
I don't get why the Autocomplete Widget is not rebuilt when the BlocBuilder is...
Am I doing something wrong, or not understanding something here ?
This is my pubspec.yaml:
# State management
flutter_bloc: ^8.1.6
Upvotes: 1
Views: 50