Skip to content

[go_router] ShellRoute needs a way to identify the current top route #140297

@getBoolean

Description

@getBoolean

Use case

I need to have the title of the current page for my custom ResponsiveScaffold widget, which places the title in a different location depending on screen size. Currently, I have to do the following with a switch case for each possible route I add

StatefulShellRoute.indexedStack(
  parentNavigatorKey: rootNavigatorKey,
  builder: (
    BuildContext context,
    GoRouterState state,
    StatefulNavigationShell navigationShell,
  ) {
    // Calculating the title using the path since the title needs to be
    // used by [ResponsiveScaffold]
    final String title = switch (state.fullPath) {
      '/books' => 'Books',
      '/books/details-:id' => state.pathParameters['id'] == null
          ? 'Book Details'
          : 'Book ${state.pathParameters['id']}',
      '/profile' => 'Profile',
      '/profile/details' => 'Profile Details',
      '/settings' => 'Settings',
      '/settings/details' => 'Setting Details',
      _ => 'Unknown',
    };
    return RootScaffoldShell(
      navigationShell: navigationShell,
      destinations: destinations,
      title: title,
    );
  },
  branches: <StatefulShellBranch>[
    ...
  ],
)

Proposal

ShellRoute.builder needs some way to know what the current top route is. None of these ideas are concrete, but a couple of options are:

  • Add argument to ShellRoute.builder/pageBuilder or GoRouterState that uniquely identifies the route
    • enum
    • route name String
    • switch pattern matching over class
Old proposal, click to expand

I propose adding a titleBuilder function parameter to GoRoute/RouteBase. It would be accessible at any time from GoRouterState, which will provide the titleBuilder from the current route. I've hacked together a pull request to demonstrate how it could be implemented. (I suspect I've implemented it in a way which would not be preferred, I'm open to suggestions for improving the PR)

Usage:

StatefulShellRoute.indexedStack(
  parentNavigatorKey: rootNavigatorKey,
  builder: (
    BuildContext context,
    GoRouterState state,
    StatefulNavigationShell navigationShell,
  ) {
    return RootScaffoldShell(
      navigationShell: navigationShell,
      destinations: destinations,
      title: state.titleBuilder?.call(context) ?? 'No Title',
    );
  },
  branches: <StatefulShellBranch>[
    GoRoute(
      path: '/books',
      titleBuilder: (BuildContext context, GoRouterState state) {
        return 'Books';
      },
      builder: (BuildContext context, GoRouterState state) {
        return BooksRootScreen(
          key: const ValueKey('BOOKS'),
        );
      },
      routes: <RouteBase>[
        GoRoute(
          path: 'details-:id',
          titleBuilder: (BuildContext context, GoRouterState state) {
            final id = state.uri.pathParameters['id'];
            return 'Book $id';
          },
          builder: (BuildContext context, GoRouterState state) {
            final id = state.pathParameters['id'];
            return BookDetailsRootScreen(id: id);
          },
        ),
      ],
    ),
    ...
  ],
)

flutter_boolean_template_WsAtWOsR2G
flutter_boolean_template_N9Ss5zDrs1

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: new featureNothing broken; request for a new capabilityc: proposalA detailed proposal for a change to Flutterp: go_routerThe go_router packagepackageflutter/packages repository. See also p: labels.r: fixedIssue is closed as already fixed in a newer version

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions