Flutter Tutorial

Navigation using GoRouter in Flutter Web

Swing the web!

Saurabh Pant
Dev Genius
Published in
4 min readMar 16, 2024

--

I’ve been working on Flutter web recently and realised that its easy to navigate between screens on app because the urls are not shown there. But on web it is not the same case. Almost all of my team members ignored this aspect all together and on a same url we were showing multiple sub screens of the same parent screen.

This also makes deep linking of screens difficult. So I looked around and found a way to do it. The method I’m sharing could be in raw state but its interesting to see this in action.

Dependency Set up

We need to first add GoRouter dependency in our pubspec.yaml file as follows

go_router: ^13.2.0

Then we need to head to our main.dart file and make some changes to the build function.

@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Web Navigation',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
routerConfig: AppRouter.dashboardRouter,
);
}

Here, we need to return MaterialApp via GoRouter using MaterialApp.router. We also need to provide a routerConfig which is a GoRouter object and we define it as follows.

abstract class AppRouter {

static final GoRouter dashboardRouter = GoRouter(
initialLocation: DashboardRoute.posts,
routes: [
DashboardScreenRouter.instance.route(),
]
);
}

Creating Routes

As shown in the video, we’ve a dashboard screen within which we’ve a left side section with some items and clicking on each item changes the content on the right.

So let’s define our routes first.

abstract class DashboardRoute {

static const posts = '/posts';
static const events = '/events';
static const users = '/users';
static const loans = '/loans';
static const details = 'details';
}

Each of the above routes are simply corresponds to the left section items as shown in the image above. Now our routes are ready to be used.

Setting up Routes

As we can see that our routes are a sub section of the dashboard screen and not the complete screen itself. So GoRouter provides an option of ShellRoutes which we can use in this scenario.

We’ll create all the shell routes and define what we want to show for each of the route as follows

ShellRoute(
routes: [
GoRoute(
path: DashboardRoute.posts,
builder: (context, state) => Container(color: Colors.brown,)
),
GoRoute(
path: DashboardRoute.events,
builder: (context, state) => Container(color: Colors.red,)
),
GoRoute(
path: DashboardRoute.loans,
builder: (context, state) => Container(color: Colors.indigo,)
),
GoRoute(
path: DashboardRoute.users,
builder: (context, state) => Container(color: Colors.deepPurple,)
),
]
);

We’ve set the screen content with a unique colour to be shown for each of the left section item. Now whichever route is selected, the content of that route will be passed as child to the ShellRoute to build the right side content on the dashboard screen.

To achieve that, we’ve to define the builder for the ShellRoute as follows

ShellRoute(
builder: (context, state, child) {
return DashboardScreen(child: child,);
},
routes: [...]
);

Cool! So now the dashboard screen will receive the content for each item from the left section via the ShellRoutes routes.

Navigating Routes from left section

Now how do we redirect to the specific route on each item click from the left section? Well! it is quite simple. On clicking the item we’ve to use the GoRouter’s go function with specific route name as follows

_itemClick(BuildContext context, int index) {
switch(index) {
case 1:
GoRouter.of(context).go(DashboardRoute.posts);
break;
case 2:
GoRouter.of(context).go(DashboardRoute.events);
break;
case 3:
GoRouter.of(context).go(LoanApplicationRoutes.loans);
break;
case 4:
GoRouter.of(context).go(DashboardRoute.users);
break;
}
}

Handling direct url navigation

Alright! So far it is shown that we can change the right side content of the dashboard screen by click and corresponding url is also updated in the browser. But if we type the url directly in the browser then the dashboard screen should open with the corresponding right side screen.

How to handle that?

To do so, we need to make some more changes in our ShellRoute builder.

First we need to add a pageIndex as a parameter in the constructor which defaults to value 1.

const DashboardScreen({super.key, required this.child, required this.pageIndex});

Then we need to identify the incoming route to our builder as follows

ShellRoute(
builder: (context, state, child) {
final String routeName = GoRouterState.of(context).matchedLocation;
final int pageIndex = switch(routeName) {
DashboardRoute.posts => 1,
'${DashboardRoute.posts}/${DashboardRoute.details}' => 1,
DashboardRoute.events => 2,
'${DashboardRoute.events}/${DashboardRoute.details}' => 2,
LoanApplicationRoutes.loans => 3,
'${LoanApplicationRoutes.loans}/${LoanApplicationRoutes.loanTab1}' => 3,
'${LoanApplicationRoutes.loans}/${LoanApplicationRoutes.loanTab2}' => 3,
'${LoanApplicationRoutes.loans}/${LoanApplicationRoutes.loanTab3}' => 3,
DashboardRoute.users => 4,
'${DashboardRoute.users}/${DashboardRoute.details}' => 4,
_ => -1,
};
return DashboardScreen(pageIndex: pageIndex, child: child,);
},

And we now we can open the correct right side content on the dashboard screen with direct url launch.

Bamn! Now the navigation on web is more easy to handle with correct screen urls. Though I’ve shared only the abstracted details of the complete dem, you can check out the project on github and try it on your own.

That is all for now! Stay tuned!

Connect with me (if the content is helpful to you ) on

Until next time…

Cheers!

--

--

App Developer (Native & Flutter) | Mentor | Writer | Youtuber @_zaqua | Traveller | Content Author & Course Instructor @Droidcon | Frontend Lead @MahilaMoney