Home > OS >  Flutter web go_router, when direct visit to: /page, how to go back to / (root)
Flutter web go_router, when direct visit to: /page, how to go back to / (root)

Time:02-02

I am using go_router and got such config:

final router = GoRouter(
  initialLocation: '/',
  routes: [
    GoRoute(path: '/', pageBuilder: (context, state) => const MaterialPage(child: MyHomePage(title: 'Flutter Demo Home Page')),),
    GoRoute(path: '/second', pageBuilder: (context, state) => const MaterialPage(child: MyHomePage(title: 'Second !')),),
  ],
);

When I visit web directly using: /second page opens correctly, but there is no way to go back to: / (no back arrow in the App bar).

If I go to / and then open /second page via: context.push("/second"); then naturally back arrow is present.

When I type URI directly in the browser, how can I make sure that App bar back arrow allows me to go to the initial page?

Full example:

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() {
  runApp(const MyApp());
}

final router = GoRouter(
  initialLocation: '/',
  routes: [
    GoRoute(path: '/', pageBuilder: (context, state) => const MaterialPage(child: MyHomePage(title: 'Flutter Demo Home Page')),),
    GoRoute(path: '/second', pageBuilder: (context, state) => const MaterialPage(child: MyHomePage(title: 'Second !')),),
  ],
);

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routerConfig: router,
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              '',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context.push("/second");
        },
        tooltip: 'Navigate',
        child: const Icon(Icons.navigate_next),
      ),
    );
  }
}

CodePudding user response:

For back to root from app bar any where use this:

 Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              '',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context, rootNavigator: true).pushAndRemoveUntil(
            MaterialPageRoute(
                builder: (context) => const  MyHomePage(title: 'Flutter Demo Home Page')),
            (route) => true);
        },
        tooltip: 'Navigate',
        child: const Icon(Icons.navigate_next),
      ),
    );
  }
}

You can use this code to back root:

  Navigator.of(context, rootNavigator: true).pushAndRemoveUntil(
            MaterialPageRoute(
                builder: (context) => const  MyHomePage(title: 'Flutter Demo Home Page')),
            (route) => true);

CodePudding user response:

The solution is to nest routes e.g. like this:

routes: [
    GoRoute(path: '/', pageBuilder: (context, state) => const MaterialPage(child: MyHomePage(title: 'Flutter Demo Home Page')), routes: [
      GoRoute(path: 'second', pageBuilder: (context, state) => const MaterialPage(child: MyHomePage(title: 'Second !'))), 
    ]),
  ],

In which case when you visit: /second directly, the / page will be on the stack.

It is possible to test the "back arrow" behavior without web browser, by going to /second directly without pushing page on stack: context.go("/second");

  • Related