Skip to content

API Quick Start

Tom Gilder edited this page Apr 25, 2021 · 9 revisions

Quick Start

Routing

Basic app routing setup:

MaterialApp.router(
  routerDelegate: RoutemasterDelegate(
    routesBuilder: (context) => RouteMap(routes: {
      '/': (routeData) => MaterialPage(child: PageOne()),
      '/two': (routeData) => MaterialPage(child: PageTwo()),
    }),
  ),
  routeInformationParser: const RoutemasterParser(),
)

Navigate:

Routemaster.of(context).push('relative-path');
Routemaster.of(context).push('/absolute-path');
Routemaster.of(context).replace('relative-path');
Routemaster.of(context).replace('/absolute-path');

Path parameters:

// Path '/products/123' will result in ProductPage(id: '123')
RouteMap(routes: {
  '/products/:id': (route) => MaterialPage(
        child: ProductPage(id: route.pathParameters['id']),
      ),
})

Query parameters:

// Path '/search?query=hello' results in SearchPage(query: 'hello')
RouteMap(routes: {
  '/search': (route) => MaterialPage(
        child: SearchPage(query: route.queryParameters['query']),
      ),
})

Get current path info within a widget:

RouteData.of(context).path; // Full path: '/product/123?query=param'
RouteData.of(context).pathParameters; // Map: {'id': '123'}
RouteData.of(context).queryParameters; // Map: {'query': 'param'}

Tabs

Setup:

RouteMap(
  routes: {
    '/': (route) => TabPage(
          child: HomePage(),
          paths: ['feed', 'settings'],
        ),
    '/feed': (route) => MaterialPage(child: FeedPage()),
    '/settings': (route) => MaterialPage(child: SettingsPage()),
  },
)

Main page:

class TabBarPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final tabPage = TabPage.of(context);

    return Scaffold(
      appBar: AppBar(
        bottom: TabBar(
          controller: tabPage.controller,
          tabs: [
            Tab(text: 'Feed'),
            Tab(text: 'Settings'),
          ],
        ),
      ),
      body: TabBarView(
        controller: tabPage.controller,
        children: [
          for (final stack in tabPage.stacks) StackNavigator(stack: stack),
        ],
      ),
    );
  }
}

Cupertino tabs

Setup:

RouteMap(
  routes: {
    '/': (route) => CupertinoTabPage(
          child: HomePage(),
          paths: ['feed', 'settings'],
        ),
    '/feed': (route) => MaterialPage(child: FeedPage()),
    '/settings': (route) => MaterialPage(child: SettingsPage()),
  },
)

Main page:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final tabState = CupertinoTabPage.of(context);

    return CupertinoTabScaffold(
      controller: tabState.controller,
      tabBuilder: tabState.tabBuilder,
      tabBar: CupertinoTabBar(
        items: [
          BottomNavigationBarItem(
            label: 'Feed',
            icon: Icon(CupertinoIcons.list_bullet),
          ),
          BottomNavigationBarItem(
            label: 'Settings',
            icon: Icon(CupertinoIcons.search),
          ),
        ],
      ),
    );
  }
}

Guarded routes

Redirect to another page if validation fails (changes URL):

'/protected-route': (route) => Guard(
    validate: (route, context) => canUserAccessPage(),
    onValidationFailed: (info, context) => Redirect('/no-access'),
    child: MaterialPage(child: ProtectedPage()),
)

Show another page if validation fails (doesn't change URL):

'/protected-route': (route) => Guard(
    validate: (route, context) => canUserAccessPage(),
    onValidationFailed: (info, context) => NoAccessPage(),
    child: MaterialPage(child: ProtectedPage()),
)

404 Page

Default page to shown on unknown URL:

RouteMap(
    onUnknownRoute: (route, context) {
        return MaterialPage(child: NotFoundPage());
    },
    routes: {
        '/': (_) => MaterialPage(child: HomePage()),
    },
)

Redirect

Redirect one route to another:

RouteMap(routes: {
    '/one': (routeData) => MaterialPage(child: PageOne()),
    '/two': (routeData) => Redirect('/one'),
})

Swap routing map

Swap the entire routing map depending on whether or not the user is logged in:

final loggedOutMap = RouteMap(
  onUnknownRoute: (route, context) => Redirect('/'),
  routes: {
    '/': (_) => MaterialPage(child: LoginPage()),
  },
);

final loggedInMap = RouteMap(
  routes: {
		// Regular app routes
  },
);

MaterialApp.router(
  routerDelegate: const RoutemasterDelegate(
    routesBuilder: (context) {
			// This will rebuild when AppState changes
      final appState = Provider.of<AppState>(context);
      return appState.isLoggedIn ? loggedInMap : loggedOutMap;
    },
  ),
  routeInformationParser: RoutemasterParser(),
);

Navigation observers

class MyObserver extends RoutemasterObserver {
	// RoutemasterObserver extends NavigatorObserver and
	// receives all nested Navigator events
  @override
  void didPop(Route route, Route? previousRoute) {
    print('Popped a route');
  }

	// Routemaster-specific observer method
  @override
  void didChangeRoute(RouteData routeData, Page page) {
    print('New route: ${routeData.path}');
  }
}

MaterialApp.router(
  routerDelegate: RoutemasterDelegate(
    observers: [MyObserver()],
    routesBuilder: (_) => routeMap,
  ),
  routeInformationParser: const RoutemasterParser(),
);

API feedback

Thank you for reading through!

I'd love any feedback about any of the API, both naming and usability. Please open an issue for any feedback ❤️

Clone this wiki locally