Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I show Dialog anywhere in the app without context?

Hello everyone this is a question I have been asking myself for quite sometime. I have also seen some answers to it, but it didn't solve my problem, some similar questions that I found are: Flutter showDialog with navigator key rather than passing context or Navigator operation requested with a context that does not include a Navigator

What I am trying to achieve is to show popup dialog anywhere in my app (so in any page of my app) from the same piece of code (so it's all concentrated). The issue is that from that piece of code I do not have access to the BuildContext, this is because I'm showing this popups based on events that do not come from a user action (like button tap), instead they could be Firestore listeners, or errors that occur deep into my code (so I can show an error message to the user), since I'm so deep into the code, usually I don't have access to the BuildContext.

In the similar questions, I found something that looks like a solution. These solutions use a GlobalKey for the navigator so can access it from anywhere, there are some different options on how to access it anywhere in the app, in my case I opted for a Singleton (my "Repository") where I store this globalKey. Then when the event is fired I use the globalKey to get the context and show a Dialog, but it throws this error:

Navigator operation requested with a context that does not include a Navigator.
The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.

@Hemanth Raj mentions that your root Widget needs to be a MaterialApp, I do have a MaterialApp as my root.

Here is an approximation of the structure of the app I have:

void main() async {

  // Here I create the navigatorKey
  GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

  // I then init my Singleton with the navigatorKey
  await repository.init(navigatorKey: navigatorKey);

  // Then I pass the navigatorKey down to my App
  runApp(MyApp(debugMode: debugMode, navigatorKey: navigatorKey));
}

class MyApp extends StatefulWidget {
  final navigatorKey;

  const MyApp({Key key, this.navigatorKey})
      : super(key: key);

  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> with WidgetsBindingObserver {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        navigatorKey: widget.navigatorKey,
        title: 'My app',
        home: SplashPage(),
        theme: _buildMyTheme(),
      );
  }
}

Then in my Repository I have a listener for firestore events. These can fire anytime after I am in my home-screen. The idea is wherever I find myself within the app, if the event is fired the popup should appear.

class Repository {

  GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;
  GlobalKey<NavigatorState> _navigatorKey;

  void init({GlobalKey<NavigatorState> navigatorKey}) {
    _navigatorKey = navigatorKey;
  }

  void _listenToEvents() {
    streamWithEvents.listen((event) {
      showDialog(
        context: navigatorKey.currentContext,
        builder: (_) => CustomMessageDialog(message: event.message),
      );
    });
  }
}
like image 469
Migalv Avatar asked Jan 17 '20 12:01

Migalv


People also ask

How do I open dialog without context in flutter?

To show a dialog we first have to get our DialogService into the ViewModel through our get_it locator and then we call showDialog on the service. We'll add this code into the showBasicDialog function. Basic Dialog should be used for showing information to the user. It takes in a title, a description and a buttonTitle.

How do I show dialog in flutter?

In its on the pressed property, we have to use the showDialog widget of flutter. It takes context and a builder. In builder, we provide the AlertDialog widget with title, content(Description of a title), and actions (Yes or no buttons), and our alert dialog box is ready to use.

How do I stop dialog close on click outside flutter?

To prevent the dialog from closing on outside barrier touch, you have to set barrierDismissible to false. It is true by default.


1 Answers

Use navigatorKey.currentState.overlay.context for showDialog's context.

like image 116
Shahin Mursalov Avatar answered Nov 08 '22 13:11

Shahin Mursalov