Features
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.
đ¨ Installation
dependencies:
routed_widget_switcher: ^2.0.1
đšī¸ Usage
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.
Unknown routes
Use the unknownRouteBuilder
to handle unexpected routes. If the delegate is not provided, a DefaultUnknownRoute
widget will be used.
Path matching
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.
Most specific match
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.
Transitions
Internally Flutters AnimatedSwitcher
widget is used for transitions, so that full API is exposed for different transition effects.
return RoutedSwitcher(
transitionBuilder: ...
duration: ...,
builders: ...,
)
Relative links and inheritance
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
],
),
),
],
);
đ Bugs/Requests
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.
đ License
MIT License