beamer 0.5.0
beamer: ^0.5.0 copied to clipboard
Route through page stacks and URLs using the Navigator 2.0 features effortlessly.
Beamer #
Handle your application routing, synchronize it with browser URL and more. Beamer uses the power of Navigator 2.0 features and implements all the underlying logic for you.
Table of Contents #
- Key Concepts
- Examples
- Books
- Deep Location
- Nested Routers (WIP)
- Usage
- Migrating from v0.4.X to v0.5.X
- Contributing
Key Concepts #
The key concept of Beamer is a BeamLocation which represents a stack of one or more pages. You will be extending BeamLocation to define your app's locations to which you can then beam to using
Beamer.of(context).beamTo(MyLocation())
or
context.beamTo(MyLocation())
You can think of it as teleporting / beaming to another place in your app. Similar to Navigator.of(context).pushReplacementNamed('/my-route'), but Beamer is not limited to a single page, nor to a push per se. You can create an arbitrary stack of pages that gets build when you beam there. Using Beamer can feel like using many of Navigator's push/pop methods at once.
Examples #
Books #
Here is a recreation of books example from this article where you can learn a lot about Navigator 2.0. This recreation starts off with the basic books example, but then proceeds in many more flows that show the full power of Beamer. See Example for full application code of this example where you can essentially learn everything you can do with Beamer.
Deep Location #
Nested Routers #
Coming soon...
Usage #
Using Beamer Around Entire App #
In order to use Beamer on your entire app, you must (as per official documentation) construct your *App widget with .router constructor to which (along with all your regular *App attributes) you provide
routerDelegatethat controls (re)building ofNavigatorpages androuteInformationParserthat decides which URI corresponds to whichRouterstate/configuration, in our case -BeamLocation.
Here you can just use the Beamer implementation of those - BeamerRouterDelegate and BeamerRouteInformationParser, to which you pass your BeamLocations. Optional notFoundPage will be shown when URI coming from browser is not among the ones that are defined in your BeamLocations.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: BeamerRouterDelegate(
initialLocation: HomeLocation(),
notFoundPage: Scaffold(body: Center(child: Text('Not found'))),
),
routeInformationParser: BeamerRouteInformationParser(
beamLocations: [
HomeLocation(),
BooksLocation(),
ArticlesLocation(),
],
),
);
}
}
An example of above book example's BeamLocations would be:
class HomeLocation extends BeamLocation {
@override
List<String> get pathBlueprints => ['/'];
@override
List<BeamPage> get pages => [
BeamPage(
key: ValueKey('home'),
child: HomeScreen(),
),
];
}
class BooksLocation extends BeamLocation {
BooksLocation({
String pathBlueprint,
Map<String, String> pathParameters,
Map<String, String> queryParameters,
Map<String, dynamic> data,
}) : super(
pathBlueprint: pathBlueprint,
pathParameters: pathParameters,
queryParameters: queryParameters,
data: data,
);
@override
List<String> get pathBlueprints => [
'/books/:bookId/genres/:genreId',
'/books/:bookId/buy',
];
@override
List<BeamPage> get pages => [
...HomeLocation().pages,
if (pathSegments.contains('books'))
BeamPage(
key: ValueKey('books-${queryParameters['title'] ?? ''}'),
child: BooksScreen(
titleQuery: queryParameters['title'] ?? '',
),
),
if (pathParameters.containsKey('bookId'))
BeamPage(
key: ValueKey('book-${pathParameters['bookId']}'),
child: BookDetailsScreen(
bookId: pathParameters['bookId'],
),
),
if (pathSegments.contains('buy'))
BeamPage(
key: ValueKey('book-${pathParameters['bookId']}-buy'),
child: BuyScreen(
book: data['book'],
),
),
if (pathSegments.contains('genres'))
BeamPage(
key: ValueKey('book-${pathParameters['bookId']}-genres'),
child: GenresScreen(
book: data['book'],
),
),
if (pathParameters.containsKey('genreId'))
BeamPage(
key: ValueKey('genres-${pathParameters['genreId']}'),
child: GenreDetailsScreen(
genre: data['genre'],
),
),
];
}
class ArticlesLocation extends BeamLocation {
ArticlesLocation({
String pathBlueprint,
Map<String, String> pathParameters,
Map<String, String> queryParameters,
Map<String, dynamic> data,
}) : super(
pathBlueprint: pathBlueprint,
pathParameters: pathParameters,
queryParameters: queryParameters,
data: data,
);
@override
List<String> get pathBlueprints => ['/articles/:articleId'];
@override
List<BeamPage> get pages => [
...HomeLocation().pages,
if (pathSegments.contains('articles'))
BeamPage(
key: ValueKey('articles'),
child: ArticlesScreen(),
),
if (pathParameters.containsKey('articleId'))
BeamPage(
key: ValueKey('articles-${pathParameters['articleId']}'),
child: ArticleDetailsScreen(
articleId: pathParameters['articleId'],
),
),
];
}
Using Beamer Deeper in Widget Tree #
Coming soon...
General Notes #
-
When extending
BeamLocation, two getters need to be implemented;pathBlueprintsandpages.pagesrepresent a stack that will be built byNavigatorwhen you beam there, andpathBlueprintsis there for Beamer to decide whichBeamLocationcorresponds to an URL coming from browser.BeamLocationtakes query and path parameters from URI. The:is necessary inpathBlueprintsif you might get path parameter from browser.
-
BeamPage's child is an arbitraryWidgetsthat represent your app screen / page.keyis important forNavigatorto optimize rebuilds. This should be an unique value for "page state".BeamPagecreatesMaterialPageRoute, but you can extendsBeamPageand overridecreateRouteto make your own implementation instead. Thekeyis important forNavigatorto optimize its rebuilds.
Note that "Navigator 1.0" can be used alongside Beamer. You can easily push or pop pages with Navigator.of(context), but those will not be contributing to the URI. This is often needed when some info/helper page needs to be shown that doesn't influence the browser's URL. And of course, when using Beamer on mobile, this is a non-issue as there is no URL.
Migrating from v0.4.X to v0.5.X #
- instead of wrapping
MaterialAppwithBeamer, use*App.router() String BeamLocation.pathBlueprintis nowList<String> BeamLocation.pathBlueprintsBeamLocation.withParametersconstructor is removed and all parameters are handled with 1 constructor. See example if you needsuper.BeamPage.pageis now calledBeamPage.child
Contributing #
This package is still in early stages. To see the upcoming features, check the Issue board.
If you notice any bugs not present in issues, please file a new issue. If you are willing to fix or enhance things yourself, you are very welcome to make a pull request. Before making a pull request;
- if you wish to solve an existing issue, please let us know in issue comments first
- if you have another enhancement in mind, create an issue for it first so we can discuss your idea




