- [Route Management](#route-management) - [How to use](#how-to-use) - [Navigation without named routes](#navigation-without-named-routes) - [Navigation with named routes](#navigation-with-named-routes) - [Send data to named Routes](#send-data-to-named-routes) - [Dynamic urls links](#dynamic-urls-links) - [Middleware](#middleware) - [Navigation without context](#navigation-without-context) - [SnackBars](#snackbars) - [Dialogs](#dialogs) - [BottomSheets](#bottomsheets) - [Nested Navigation](#nested-navigation) # Route Management This is the complete explanation of all there is to Getx when the matter is route management. ## How to use Add this to your pubspec.yaml file: ```yaml dependencies: get: ``` If you are going to use routes/snackbars/dialogs/bottomsheets without context, or use the high-level Get APIs, you need to simply add "Get" before your MaterialApp, turning it into GetMaterialApp and enjoy! ```dart GetMaterialApp( // Before: MaterialApp( home: MyHome(), ) ``` ## Navigation without named routes To navigate to a new screen: ```dart Get.to(NextScreen()); ``` To close snackbars, dialogs, bottomsheets, or anything you would normally close with Navigator.pop(context); ```dart Get.back(); ``` To go to the next screen and no option to go back to the previous screen (for use in SplashScreens, login screens and etc.) ```dart Get.off(NextScreen()); ``` To go to the next screen and cancel all previous routes (useful in shopping carts, polls, and tests) ```dart Get.offAll(NextScreen()); ``` To navigate to the next route, and receive or update data as soon as you return from it: ```dart var data = await Get.to(Payment()); ``` on other screen, send a data for previous route: ```dart Get.back(result: 'success'); ``` And use it: ex: ```dart if(data == 'success') madeAnything(); ``` Don't you want to learn our syntax? Just change the Navigator (uppercase) to navigator (lowercase), and you will have all the functions of the standard navigation, without having to use context Example: ```dart // Default Flutter navigator Navigator.of(context).push( context, MaterialPageRoute( builder: (BuildContext context) { return HomePage(); }, ), ); // Get using Flutter syntax without needing context navigator.push( MaterialPageRoute( builder: (_) { return HomePage(); }, ), ); // Get syntax (It is much better, but you have the right to disagree) Get.to(HomePage()); ``` ## Navigation with named routes - If you prefer to navigate by namedRoutes, Get also supports this. To navigate to nextScreen ```dart Get.toNamed("/NextScreen"); ``` To navigate and remove the previous screen from the tree. ```dart Get.offNamed("/NextScreen"); ``` To navigate and remove all previous screens from the tree. ```dart Get.offAllNamed("/NextScreen"); ``` To define routes, use GetMaterialApp: ```dart void main() { runApp( GetMaterialApp( initialRoute: '/', getPages: [ GetPage(name: '/', page: () => MyHomePage()), GetPage(name: '/second', page: () => Second()), GetPage( name: '/third', page: () => Third(), transition: Transition.zoom ), ], ) ); } ``` To handle navigation to non-defined routes (404 error), you can define an unknownRoute page in GetMaterialApp. ```dart void main() { runApp( GetMaterialApp( unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()), initialRoute: '/', getPages: [ GetPage(name: '/', page: () => MyHomePage()), GetPage(name: '/second', page: () => Second()), ], ) ); } ``` ### Send data to named Routes Just send what you want for arguments. Get accepts anything here, whether it is a String, a Map, a List, or even a class instance. ```dart Get.toNamed("/NextScreen", arguments: 'Get is the best'); ``` on your class or controller: ```dart print(Get.arguments); //print out: Get is the best ``` ### Dynamic urls links Get offer advanced dynamic urls just like on the Web. Web developers have probably already wanted this feature on Flutter, and most likely have seen a package promise this feature and deliver a totally different syntax than a URL would have on web, but Get also solves that. ```dart Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo"); ``` on your controller/bloc/stateful/stateless class: ```dart print(Get.parameters['id']); // out: 354 print(Get.parameters['name']); // out: Enzo ``` You can also receive NamedParameters with Get easily: ```dart void main() { runApp( GetMaterialApp( initialRoute: '/', getPages: [ GetPage( name: '/', page: () => MyHomePage(), ), GetPage( name: '/profile/', page: () => MyProfile(), ), //You can define a different page for routes with arguments, and another without arguments, but for that you must use the slash '/' on the route that will not receive arguments as above. GetPage( name: '/profile/:user', page: () => UserProfile(), ), GetPage( name: '/third', page: () => Third(), transition: Transition.cupertino ), ], ) ); } ``` Send data on route name ```dart Get.toNamed("/profile/34954"); ``` On second screen take the data by parameter ```dart print(Get.parameters['user']); // out: 34954 ``` or send multiple parameters like this ```dart Get.toNamed("/profile/34954?flag=true&country=italy"); ``` or ```dart var parameters = {"flag": "true","country": "italy",}; Get.toNamed("/profile/34954", parameters: parameters); ``` On second screen take the data by parameters as usually ```dart print(Get.parameters['user']); print(Get.parameters['flag']); print(Get.parameters['country']); // out: 34954 true italy ``` And now, all you need to do is use Get.toNamed() to navigate your named routes, without any context (you can call your routes directly from your BLoC or Controller class), and when your app is compiled to the web, your routes will appear in the url <3 ### Middleware If you want to listen Get events to trigger actions, you can to use routingCallback to it ```dart GetMaterialApp( routingCallback: (routing) { if(routing.current == '/second'){ openAds(); } } ) ``` If you are not using GetMaterialApp, you can use the manual API to attach Middleware observer. ```dart void main() { runApp( MaterialApp( onGenerateRoute: Router.generateRoute, initialRoute: "/", navigatorKey: Get.key, navigatorObservers: [ GetObserver(MiddleWare.observer), // HERE !!! ], ), ); } ``` Create a MiddleWare class ```dart class MiddleWare { static observer(Routing routing) { /// You can listen in addition to the routes, the snackbars, dialogs and bottomsheets on each screen. ///If you need to enter any of these 3 events directly here, ///you must specify that the event is != Than you are trying to do. if (routing.current == '/second' && !routing.isSnackbar) { Get.snackbar("Hi", "You are on second route"); } else if (routing.current =='/third'){ print('last route called'); } } } ``` Now, use Get on your code: ```dart class First extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( icon: Icon(Icons.add), onPressed: () { Get.snackbar("hi", "i am a modern snackbar"); }, ), title: Text('First Route'), ), body: Center( child: ElevatedButton( child: Text('Open route'), onPressed: () { Get.toNamed("/second"); }, ), ), ); } } class Second extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( icon: Icon(Icons.add), onPressed: () { Get.snackbar("hi", "i am a modern snackbar"); }, ), title: Text('second Route'), ), body: Center( child: ElevatedButton( child: Text('Open route'), onPressed: () { Get.toNamed("/third"); }, ), ), ); } } class Third extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Third Route"), ), body: Center( child: ElevatedButton( onPressed: () { Get.back(); }, child: Text('Go back!'), ), ), ); } } ``` ## Navigation without context ### SnackBars To have a simple SnackBar with Flutter, you must get the context of Scaffold, or you must use a GlobalKey attached to your Scaffold ```dart final snackBar = SnackBar( content: Text('Hi!'), action: SnackBarAction( label: 'I am a old and ugly snackbar :(', onPressed: (){} ), ); // Find the Scaffold in the widget tree and use // it to show a SnackBar. Scaffold.of(context).showSnackBar(snackBar); ``` With Get: ```dart Get.snackbar('Hi', 'i am a modern snackbar'); ``` With Get, all you have to do is call your Get.snackbar from anywhere in your code or customize it however you want! ```dart Get.snackbar( "Hey i'm a Get SnackBar!", // title "It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", // message icon: Icon(Icons.alarm), shouldIconPulse: true, onTap:(){}, barBlur: 20, isDismissible: true, duration: Duration(seconds: 3), ); ////////// ALL FEATURES ////////// // Color colorText, // Duration duration, // SnackPosition snackPosition, // Widget titleText, // Widget messageText, // bool instantInit, // Widget icon, // bool shouldIconPulse, // double maxWidth, // EdgeInsets margin, // EdgeInsets padding, // double borderRadius, // Color borderColor, // double borderWidth, // Color backgroundColor, // Color leftBarIndicatorColor, // List boxShadows, // Gradient backgroundGradient, // TextButton mainButton, // OnTap onTap, // bool isDismissible, // bool showProgressIndicator, // AnimationController progressIndicatorController, // Color progressIndicatorBackgroundColor, // Animation progressIndicatorValueColor, // SnackStyle snackStyle, // Curve forwardAnimationCurve, // Curve reverseAnimationCurve, // Duration animationDuration, // double barBlur, // double overlayBlur, // Color overlayColor, // Form userInputForm /////////////////////////////////// ``` If you prefer the traditional snackbar, or want to customize it from scratch, including adding just one line (Get.snackbar makes use of a mandatory title and message), you can use `Get.rawSnackbar();` which provides the RAW API on which Get.snackbar was built. ### Dialogs To open dialog: ```dart Get.dialog(YourDialogWidget()); ``` To open default dialog: ```dart Get.defaultDialog( onConfirm: () => print("Ok"), middleText: "Dialog made in 3 lines of code" ); ``` To close the dialog and return a result use `Get.closeDialog` providing the `result` to return to the awaited `Get.dialog` call. ```dart Widget buttonWithResult({ required final String text, required final bool result, }) => TextButton( onPressed: () { Get.closeDialog(result: result); }, child: Text(text), ); bool? delete = await Get.dialog( AlertDialog( content: const Text('Are you sure you would like to delete?'), actions: [ buttonWithResult(text: 'No', result: false), buttonWithResult(text: 'Yes', result: true), ], ), ); if (delete != null && delete) { // Perform the deletion } ``` You can also use Get.generalDialog instead of showGeneralDialog. For all other Flutter dialog widgets, including cupertinos, you can use Get.overlayContext instead of context, and open it anywhere in your code. For widgets that don't use Overlay, you can use Get.context. These two contexts will work in 99% of cases to replace the context of your UI, except for cases where inheritedWidget is used without a navigation context. ### BottomSheets Get.bottomSheet is like showModalBottomSheet, but don't need of context. ```dart Get.bottomSheet( Container( child: Wrap( children: [ ListTile( leading: Icon(Icons.music_note), title: Text('Music'), onTap: () {} ), ListTile( leading: Icon(Icons.videocam), title: Text('Video'), onTap: () {}, ), ], ), ) ); ``` ## Nested Navigation Get made Flutter's nested navigation even easier. You don't need the context, and you will find your navigation stack by Id. - NOTE: Creating parallel navigation stacks can be dangerous. The ideal is not to use NestedNavigators, or to use sparingly. If your project requires it, go ahead, but keep in mind that keeping multiple navigation stacks in memory may not be a good idea for RAM consumption. See how simple it is: ```dart Navigator( key: Get.nestedKey(1), // create a key by index initialRoute: '/', onGenerateRoute: (settings) { if (settings.name == '/') { return GetPageRoute( page: () => Scaffold( appBar: AppBar( title: Text("Main"), ), body: Center( child: TextButton( color: Colors.blue, onPressed: () { Get.toNamed('/second', id:1); // navigate by your nested route by index }, child: Text("Go to second"), ), ), ), ); } else if (settings.name == '/second') { return GetPageRoute( page: () => Center( child: Scaffold( appBar: AppBar( title: Text("Main"), ), body: Center( child: Text("second") ), ), ), ); } } ), ```