tmaihoff
tmaihoff

Reputation: 3570

How to prevent going back to previous page on Flutter Web via browser back button?

After a user successfully logged in in my Flutter web app, it should be taken to a dashboard view.

The user then should not be able to navigate back to the login screen by pressing the browser back button.

I tried a lot of things, replacing the route, popping the route and then pushing the next route, all did not work.

Also using WillPopScope in the dashboard page does not work. Pressing the browser back button does not fire onWillPop.

Found some similar questions, but they all end up suggesting WillPopScope or replacing the route, both did not work for me.

Any idea what I could do?

Upvotes: 2

Views: 4206

Answers (4)

DevQt
DevQt

Reputation: 719

If you want to disable the browser's back button for your app.

I encountered the same issue, and I fixed it with this simple GoRouter configuration:

late final router = GoRouter(
  navigatorKey: navigatorKey,
  initialLocation: '/',
  routerNeglect: true, 👈 set this to true; default is false
  routes: <RouteBase>[
      // your routes here...
  ],
);

I can now prevent the user from navigating back through the browser's back button.

Important notes: I've tested it out in Google Chrome, Mozilla Firefox, and Microsoft Edge. It prevents navigating back to the previous path if it's done using the browser's back button. I considered this a working solution since if a developer wanted the user to navigate to a specific path, then they must provide it in the page section of their app where the user can interact with it.

Also, note that I am using go_router 14.2.1.

EDIT

I'm not sure if this is possible, but if so, you could do something like this:

late final router = GoRouter(
  navigatorKey: navigatorKey,
  initialLocation: '/',
  routerNeglect: toggleVariable, 👈 toggle based on condition bool variable
  routes: <RouteBase>[
      // your routes here...
  ],
);

I hope it helps!

Upvotes: 0

Code on the Rocks
Code on the Rocks

Reputation: 17794

go_router handles this pretty easily. In your router config, just add an onExit function to the route you want to add the popup to that asks if the user wants to leave:

final router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const Home(),
    ),
    GoRoute(
      path: '/screen_one',
      builder: (context, state) => const ScreenOne(),
      onExit: (context, state) async {
        bool confirm = await showDialog<bool>(
              context: context,
              builder: (context) {
                return Center(
                  child: ConstrainedBox(
                    constraints: const BoxConstraints(
                      maxWidth: 400,
                    ),
                    child: Dialog(
                      backgroundColor: Colors.blue.shade200,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10),
                      ),
                      child: Padding(
                        padding: const EdgeInsets.all(24.0),
                        child: Column(
                          mainAxisSize: MainAxisSize.min,
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: [
                            const Center(
                              child: Text(
                                'Go Back?',
                                style: TextStyle(
                                  fontSize: 28,
                                ),
                              ),
                            ),
                            const SizedBox(height: 16),
                            ElevatedButton(
                              onPressed: () {
                                Navigator.of(context).pop(true);
                              },
                              child: const Text('Yes, Start Over'),
                            ),
                            const SizedBox(height: 16),
                            ElevatedButton(
                              onPressed: () {
                                Navigator.of(context).pop(false);
                              },
                              child: const Text('No, Cancel'),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                );
              },
            ) ??
            false;

        return confirm;
      },
    ),
    GoRoute(
      path: '/screen_two',
      builder: (context, state) => const ScreenTwo(),
    ),
  ],
);

Upvotes: 1

tmaihoff
tmaihoff

Reputation: 3570

Seems like you can't intercept the browser back buttons.

I solved the problem by using a RouteGuard of the auto_route package which intercepts the navigation and checks if the user is authenticated or not. If the user is already authenticated, the navigation to the Signin page is canceled.

Check the auto_route package for examples and further explanation: https://pub.dev/packages/auto_route#route-guards

Upvotes: 4

Ozan Taskiran
Ozan Taskiran

Reputation: 3572

Wrap it inside a WillPopScope and return false

WillPopScope(
      onWillPop: () async => Future.value(false),
      child: DashboardView(),
      ),

Upvotes: -1

Related Questions