Declaratively switch child widgets based on the current Router
location.
class SideBar extends StatelessWidget {
Widget build(_){
return RoutedSwitcher(
builders: (_) => [
Routed('/', MainMenu.new),
Routed('/dashboard', DashboardMenu.new),
]);
}
}
Intended as a complimentary package for any Router
(aka Nav2) implementation. Including popular routing solutions like GoRouter, RouteMaster or VRouter.
This is useful in 2 primary use cases:
- when you have scaffolding around your Navigator, like a
SideBar
or aTitleBar
and you would like it to react to location changes - when multiple paths resolve to the same
Page
and you want to move subsequent routing further down the tree
Note: This package does not provide any control of the routers location, it simply reads the current location and responds accordingly.
dependencies:
routed_widget_switcher: ^2.0.1
Place the widget anywhere below the root Router
widget and define the paths you would like to match. By default paths are considered to be case-insensitive, and treated as prefixes, but this can be disabled using the .exact
extension method, or usePrefix: false
setting.
All widgets are lazy loaded, and can be defined using a closure: () => MyPage
or a constructor tear-off: MyPage.new
:
return RoutedSwitcher(
caseSensitive: true,
builders: (info) => [
// use '.exact' to match only '/'
Routed('/', MainMenu.new).exact,
// match anything prefixed with `/dashboard`
Routed('/dashboard', DashboardMenu.new),
// use the closure, so we can access query params
Routed('/settings', () => SettingsMenu(type: info.queryParams['type'])),
],
);
As shown above, the builders
delegate passes a RoutedInfo
object which contains info about the current match. This includes:
- url
- matchingRoute
- pathParams
- queryParams
You can also call RoutedInfo.of(context)
from any descendant widgets to access the info on demand.
Use the unknownRouteBuilder
to handle unexpected routes. If the delegate is not provided, a DefaultUnknownRoute
widget will be used.
Paths can be defined as simple strings like /user/new
or user/:userId
, or use regular expression syntax like r'/user/:id(\d+)'
. See pathToRegExp
library for more details on advanced use cases: https://pub.dev/packages/path_to_regexp.
In addition to the matching performed by pathToRegExp
, a wildcard *
character can be used to match any location.
RoutedSwitcher
will attempt to use the most specific match. For example, the url /users/new
matches all three of these builders:
Routed('/users/:userId', TeamDetails.new),
Routed('/users/new', NewTeamForm.new),
Routed('*', TeamStandings.new),
Since /users/new
is the more exact match, it will be the one to render, it does not matter which order you declare them in. /users/:userId
would go next, with the wildcard *
finally matching last.
Internally Flutters AnimatedSwitcher
widget is used for transitions, so that full API is exposed for different transition effects.
return RoutedSwitcher(
transitionBuilder: ...
duration: ...,
builders: ...,
)
Nested switchers are supported to any depth, and relative paths can be defined by omitting the /
character.
return RoutedSwitcher(
builders: (_) => [
Routed(
'/messages',
() => RoutedSwitcher(
builders: (_) => [
Routed('', Inbox.new), // -> /messages/
Routed('inbox', Inbox.new), // -> /messages/inbox
Routed('outbox', Outbox.new), // -> /messages/outbox
],
),
),
],
);
If you encounter any problems please open an issue. If you feel the library is missing a feature, please raise a ticket on Github and we'll look into it. Pull request are welcome.
MIT License