go_router

Sub-routes

Every top-level route will create a navigation stack of one page. To produce an entire stack of pages, you can use sub-routes. In the case that a top-level route only matches part of the location, the rest of the location can be matched against sub-routes. The rules are still the same, i.e. that only a single route at any level will be matched and the entire location much be matched.

For example, the location /family/f1/person/p2, can be made to match multiple sub-routes to create a stack of pages:

/             => HomeScreen()
  family/f1   => FamilyScreen('f1')
    person/p2 => PersonScreen('f1', 'p2') ← showing this page, Back pops the stack ↑

To specify a set of pages like this, you can use sub-page routing via the routes parameter to the GoRoute constructor:

final _router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => HomeScreen(families: Families.data),
      routes: [
        GoRoute(
          path: 'family/:fid',
          builder: (context, state) {
            final family = Families.family(state.params['fid']!);
            return  FamilyScreen(family: family);
          },
          routes: [
            GoRoute(
              path: 'person/:pid',
              builder: (context, state) {
                final family = Families.family(state.params['fid']!);
                final person = family.person(state.params['pid']!);

                return PersonScreen(family: family, person: person);
              },
            ),
          ],
        ),
      ],
    ),
  ],
);

go_router will match the routes all the way down the tree of sub-routes to build up a stack of pages. If go_router doesn't find a match, then the error handler will be called.

Also, go_router will pass parameters from higher level sub-routes so that they can be used in lower level routes, e.g. fid is matched as part of the family/:fid route, but it's passed along to the person/:pid route because it's a sub-route of the family/:fid route.