Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access Provided (Provider.of()) value inside showModalBottomSheet?

I have a FloatingActionButton inside a widget tree which has a BlocProvider from flutter_bloc. Something like this:

BlocProvider(
  builder: (context) {
    SomeBloc someBloc = SomeBloc();
    someBloc.dispatch(SomeEvent());

    return someBloc;
  },
  child: Scaffold(
    body: ...
    floatingActionButton: FloatingActionButton(
      onPressed: _openFilterSchedule,
      child: Icon(Icons.filter_list),
    ),
  )
);

Which opens a modal bottom sheet:

void _openFilterSchedule() {
    showModalBottomSheet<void>(
      context: context,
      builder: (BuildContext context) {
        return TheBottomSheet();
      },
    );
  }

I am trying to access SomeBloc using BlocProvider.of<SomeBloc>(context) inside TheBottomSheet but I get the following error:

BlocProvider.of() called with a context that does not contain a Bloc of type SomeBloc.

I have tried to use the solution described in https://stackoverflow.com/a/56533611/2457045 but only works for BottomSheet and not ModalBottomSheet.


Note: This is not restricted to BlocProvider or flutter_bloc. Any Provider from the provider package has the same behaviour.

How can I access BlocProvider.of<SomeBloc>(context) inside the showModalBottomSheet?

In case it's not possible to do that, how to adapt https://stackoverflow.com/a/56533611/2457045 solution to Modal Bottom Sheet?

like image 841
Henrique Arthur Avatar asked Aug 18 '19 19:08

Henrique Arthur


2 Answers

InheritedWidgets, and therefore Providers, are scoped to the widget tree. They cannot be accessed outside of that tree.

The thing is, using showDialog and similar functions, the dialog is located in a different widget tree – which may not have access to the desired provider.

It is therefore necessary to add the desired providers in that new widget tree:

void myShowDialog() {
  final myModel = Provider.of<MyModel>(context, listen: false);
  showDialog(
    context: context,
    builder: (_) {
      return Provider.value(value: myModel, child: SomeDialog());
    },
  );
}
like image 157
Rémi Rousselet Avatar answered Nov 13 '22 05:11

Rémi Rousselet


You need move Provider to top layer(MaterialApp)

According to picture, Dialog widget is under MaterialApp, so this is why you using wrong context

enter image description here

like image 20
CH Wing Avatar answered Nov 13 '22 06:11

CH Wing