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),
);
});
}
}
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.
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.
To prevent the dialog from closing on outside barrier touch, you have to set barrierDismissible to false. It is true by default.
Use navigatorKey.currentState.overlay.context
for showDialog
's context.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With