I'm new to Flutter and I'm trying to implement Bloc pattern for my notes app.
So I have to use Bloc in button on AppBar and in NotesView. It works fine in NoteView, but when I added it to the NoteFilterButton, I'm getting the error:
BlocProvider.of() called with a context that does not contain a Bloc of type NotesBloc.
I/flutter ( 6501): No ancestor could be found starting from the context that was passed to
I/flutter ( 6501): BlocProvider.of
I/flutter ( 6501):
I/flutter ( 6501): This can happen if the context you used comes from a widget above the BlocProvider.
I/flutter ( 6501):
I/flutter ( 6501): The context used was: BlocBuilder
I/flutter ( 6501): _BlocBuilderBaseState
class NotesPage extends StatelessWidget{
NotesPage();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
NoteFilterButton()
],
),
body: BlocProvider
create: (context) => NotesBloc(notesRepository: FirebaseNotesRepository()),
child: NotesView(),
),
);
}
}
my NoteFilterButton:
`class NoteFilterButton extends StatelessWidget{
@override
Widget build(BuildContext context) {
return BlocBuilder<NotesBloc, NotesState>(
builder: (context, state){
return IconButton(
icon: Icon(Icons.sort),
onPressed: (){
showDialog(barrierDismissible: false, context: context,builder: (_) =>
SortDialog(initialSortOption: state.sortOption, initialOrderOption: state.orderOption,) ).then((res){
...
});
},
);
}
);
}
}`
What am I missing here?
The BlocProvider need to be in parent widget of NoteFilterButton(), try to change it at Scaffold
BlocProvider(
create: (context) => NotesBloc(notesRepository: FirebaseNotesRepository()),
child: Scaffold(),)
Hi @YanaKrivitskaya ! ๐
In your setup BlocProvider is below your button so you won't have access to it.
Consider lifting up your BlocProvider above Scaffold.
If you're only needing NotesBloc in your dialog then consider removing the BlocBuilder and passing your bloc like so:
return IconButton(
icon: Icon(Icons.sort),
onPressed: (){
showDialog(barrierDismissible: false, context: context,builder: (_) =>
BlocProvider.value(value: context.bloc<NotesBloc>(), child: SortDialog())).then((res){
...
});
},
);
This way you won't need to pass all those parameters and just consume your bloc state in your SortDialog using BlocBuilder, BlocListener, BlocConsumer or even just context.bloc<NotesBloc>().state if you just need to grab the current state of the bloc.
Hope that helps you ๐
@RollyPeres Thank you for your answer!
Maybe it's a stupid question, but it's not obvious to me how to get state in Sort Dialog.
So I've updated it to :
`showDialog(barrierDismissible: false, context: context,builder: (_) =>
BlocProvider.value(
value: context.bloc
child: SortDialog())
).then((res){
});`
And In my Sort Dialog I'm trying to use BlocBuilder:
`class SortDialog extends StatefulWidget {
NotesBloc _notesBloc;
@override
_SortDialogState createState() => new _SortDialogState();
}
class _SortDialogState extends State
NotesBloc _notesBloc;
@override
void initState() {
super.initState();
_notesBloc = BlocProvider.of
}
@override
Widget build(BuildContext context){
return BlocBuilder<NotesBloc, NotesState>(
builder: (context, state){
print(state.sortOption);
return new AlertDialog(
title: Text('Sort by'),
actions: <Widget>[
FlatButton(
child: Text('Done'),
onPressed: () {Navigator.pop(context, new SortOrder(_selectedSortOption, _selectedOrderOption));},
),
FlatButton(
child: Text('Cancel'),
onPressed: () {Navigator.pop(context);},
),
],
content: SingleChildScrollView(
child: Column(
children: <Widget>[
_sortOptions(),
Divider(color: ColorsPalette.blueHorizon),
_orderOptions()
],
),
),
);
}
);
}`
Still getting error
BlocProvider.of() called with a context that does not contain a Bloc of type NotesBloc.
I/flutter ( 6501): No ancestor could be found starting from the context that was passed to
I/flutter ( 6501): BlocProvider.of
I/flutter ( 6501):
No worries @YanaKrivitskaya , there's no such thing as stupid question in dev world โ
Please be explicit with type when using BlocProvider.value e.g.: value: context.bloc<NotesBloc>(),
Your SortDialog widget can be Stateless unless you have some additional state to keep track of.
You can simply use BlocBuilder like you already do, without the need to manually retrieve the bloc in initState since BlocBuilder will do just that for you.
Don't forget to move your initial BlocProvider on top of Scaffold ๐ค
Hope that gets you on the right track! ๐
@RollyPeres Moving BlocProvider over the Scaffold did the trick!
Thanks again for your help, you were very responsive.
Most helpful comment
@RollyPeres Moving BlocProvider over the Scaffold did the trick!
Thanks again for your help, you were very responsive.