I am trying to achieve a persistent menu (side-bar) in flutter web. I can achieve that as long as all the pages in the app are directly listed as menu items.
The problem is I cannot get the nested pages (pages not listed in the side menu but open on some button click from inside another page) to open in the "content area".
I have tried a LOT of stuff from Navigation Rail to GoRouter to different packages for sidebar.
I don’t know what code to post here.
My project also uses Getx.
With whatever code I have I can open 1st level pages in the content area but the nested pages load as a new page and the side-bar is lost.
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
///
final MyMenuController menuController = Get.put(MyMenuController());
///
return Scaffold(
appBar: AppBar(
title: const Text('Side Menu Example'),
),
body: Row(
children: [
Expanded(
child: Container(
color: Colors.blue,
child: ListView(
children: [
ListTile(
title: const Text('Page 1'),
selected: menuController.selectedIndex.value == 0,
onTap: () {
menuController.selectTab(0);
},
),
ListTile(
title: const Text('Page 2'),
selected: menuController.selectedIndex.value == 1,
onTap: () {
menuController.selectTab(1);
},
),
ListTile(
title: const Text('Page 3'),
selected: menuController.selectedIndex.value == 2,
onTap: () {
menuController.selectTab(2);
},
),
],
),
),
),
Expanded(
flex: 5,
child: Container(color: Colors.white, child: const SizedBox() //
Obx(
() {
switch (menuController.selectedIndex.value) {
case 0:
return const Page1();
case 1:
return const Page2();
case 2:
return const Page3();
default:
return Container();
return Container();
}
},
),
),
),
],
),
// ),
);
}
}
Just in case somebody wants to say "Show us what you have tried". I have tried a bunch of stuff nothing worked out so far. If you know how to achieve this, please point me in the right direction.
2
Answers
To know first
You need first to understand that the
Navigator
widget lists all opened routes as "siblings", when you do have aPage1
that is a route in your Navigator, you can think of it like it is a child of theNavigator
when you open another route of thatNavigator
, it is opened as a sibling for thatPage2
.The Navigator widget is an
InheritedWidget
, which means that using Getx for routing disables the interaction with theBuildContext
of it (with
Get.to(Widget())
as an example ), which you need to avoid/not use.How this relates to your case?
by understanding this, if you have a menu bar in
Page1
, it will not be shown inPage2
since it is a different route, which is why you get that behavior in your app.How to fix/achieve your expected behavior?
the
Navigator
widget is anInheritedWidget
, which means that to get access to it from your app, we useNavigator.of(context)
, this gets up theNavigator
widget that is contained by default in theMaterialApp
of our app.for having an app that will always show the persistent navigation bar even if we do navigate to nested routes in the app, we need to create a new
Navigator
widget that is upfront the screen which has the menu bar.so when you navigate between pages, always the
ScreenWithMenuBar
will be shown.I am using GoRouter as of a couple of days and still trying to understand some key concepts but this is how I managed to implement a nested navigation.
== Router ==
ShellRoute
as that returns theRootLayout
where I have anAdaptiveNavigator
and expects a child that is the screen you want to display_parentKey
toparentNavigatorKey
CupertinoPage
,MaterialPage
orCustomTransitionPage
where you get to add your own magic== RootLayout ==
AdaptiveNavigation
simply checks layout size and if Desktop it will display aNavigationRail
or MobileBottomNavigationBar
_Switcher
is just a class that provides some basic animation when the layout size changesOverall what is happening here is one router with 2 states that has as root a widget with a navbar and a child Widget that is being passed down from GoRouter.
Please let me know if you require any further details.