All Projects → Milad-Akarie → Auto_route_library

Milad-Akarie / Auto_route_library

Flutter route generator

Programming Languages

dart
5743 projects

Projects that are alternatives of or similar to Auto route library

qlevar router
Manage you project Routes. Create nested routes. Simply navigation without context to your pages. Change only one sub widget in your page when navigating to new route.
Stars: ✭ 51 (-88.25%)
Mutual labels:  router, navigation
go router
The purpose of the go_router for Flutter is to use declarative routes to reduce complexity, regardless of the platform you're targeting (mobile, web, desktop), handling deep linking from Android, iOS and the web while still allowing an easy-to-use developer experience.
Stars: ✭ 380 (-12.44%)
Mutual labels:  router, navigation
Parrot
Web router specially designed for building SPAs using Meteor
Stars: ✭ 75 (-82.72%)
Mutual labels:  router, navigation
Android Router
An android componentization protocol framework, used for decoupling complex project. Android高性能轻量级路由框架
Stars: ✭ 208 (-52.07%)
Mutual labels:  router, navigation
Hybrid Navigation
React Native Navigation that supports seamless navigation between Native and React.
Stars: ✭ 258 (-40.55%)
Mutual labels:  router, navigation
Marshroute
Marshroute is an iOS Library for making your Routers simple but extremely powerful
Stars: ✭ 208 (-52.07%)
Mutual labels:  router, navigation
navigation-skeleton
This component allows you to show skeletons of pages during navigation process.
Stars: ✭ 16 (-96.31%)
Mutual labels:  router, navigation
Hookrouter
The flexible, and fast router for react that is entirely based on hooks
Stars: ✭ 1,200 (+176.5%)
Mutual labels:  router, navigation
browser
Routing and Navigation for browser apps
Stars: ✭ 31 (-92.86%)
Mutual labels:  router, navigation
universal-router
↩️ Router for every occasions
Stars: ✭ 64 (-85.25%)
Mutual labels:  router, navigation
Arouter
💪 A framework for assisting in the renovation of Android componentization (帮助 Android App 进行组件化改造的路由框架)
Stars: ✭ 13,587 (+3030.65%)
Mutual labels:  router, navigation
React Native Simple Router
A community maintained router component for React Native
Stars: ✭ 266 (-38.71%)
Mutual labels:  router, navigation
React Router Native Stack
A stack navigation component for react-router-native
Stars: ✭ 171 (-60.6%)
Mutual labels:  router, navigation
Swiftuirouter
Routing in SwiftUI
Stars: ✭ 242 (-44.24%)
Mutual labels:  router, navigation
Redux Saga Router
A router for Redux Saga
Stars: ✭ 153 (-64.75%)
Mutual labels:  router, navigation
Helm
A graph-based SwiftUI router
Stars: ✭ 64 (-85.25%)
Mutual labels:  router, navigation
Ng2 Breadcrumbs
A breadcrumb service for the Angular 7 router
Stars: ✭ 61 (-85.94%)
Mutual labels:  router, navigation
Corenavigation
📱📲 Navigate between view controllers with ease. 💫 🔜 More stable version (written in Swift 5) coming soon.
Stars: ✭ 69 (-84.1%)
Mutual labels:  router, navigation
react-native-boilerplate
Ready-made structure of your next React Native application within a few minutes.
Stars: ✭ 36 (-91.71%)
Mutual labels:  router, navigation
Frontexpress
An Express.js-Style router for the front-end
Stars: ✭ 263 (-39.4%)
Mutual labels:  router, navigation

MIT License stars pub version Discord Badge

Check out the new docs! https://autoroute.vercel.app


Introduction

What is AutoRoute?

It’s a Flutter navigation package, it allows for strongly-typed arguments passing, effortless deep-linking and it uses code generation to simplify routes setup, with that being said it requires a minimal amount of code to generate everything needed for navigation inside of your App.

Why AutoRoute?

If your App requires deep-linking or guarded routes or just a clean routing setup you'll need to use named/generated routes and you’ll end up writing a lot of boilerplate code for mediator argument classes, checking for required arguments, extracting arguments and a bunch of other stuff. AutoRoute does all that for you and much more.

Installation

dependencies:
  auto_route: [latest-version]

dev_dependencies:
  auto_route_generator: [latest-version]
  build_runner:

Setup and Usage


Create a placeholder class and annotate it with @MaterialAutoRouter which takes a list of routes as a required argument. Note: The name of the router must be prefixed with $ so we will have a generated class with the same name minus the $.

// @CupertinoAutoRouter
// @AdaptiveAutoRouter
// @CustomAutoRouter
@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(page: BookListPage, initial: true),
    AutoRoute(page: BookDetailsPage),
  ],
)
class $AppRouter {}

Tip: You can Shorten auto-generated route names from e.g. BookListPageRoute to BookListRoute using the replaceInRouteName argument.

Now simply run the generator

Use the [watch] flag to watch the files' system for edits and rebuild as necessary.

flutter packages pub run build_runner watch

if you want the generator to run one time and exits use

flutter packages pub run build_runner build

Finalize the setup

after you run the generator your router class will be generated, hook it up with MaterialApp.

   final _appRouter = AppRouter()
   ...
  Widget build(BuildContext context){
      return MaterialApp.router(
             routerDelegate: _appRouter.delegate(...initialConfig),
             routeInformationParser: _appRouter.defaultRouteParser(),
         ),
  }

Generated Routes


A PageRouteInfo object will be generated for every declared AutoRoute, These objects hold path information plus strongly-typed page arguments which are extracted from the page's default constructor.

class BookListRoute extends PageRouteInfo {
  const BookListRoute() : super(name, path: '/books');

  static const String name = 'BookListRoute';
}

if the declared route has children AutoRoute will add a children parameter to its constructor to be used in deep-linking. more on that here

class UserRoute extends PageRouteInfo {
   UserRoute({List<PagerouteInfo> children}) :
    super(
		   name, 
		   path: '/user/:id',
		   initialChildren: children);
  static const String name = 'UserRoute';
}

Navigation

AutoRouter offers the same known push, pop and friends methods to manipulate the pages stack using the generated PageRouteInfo objects.

// get the scoped router by calling
AutoRouter.of(context)
// or using the extension
context.router

// adds a new entry to pages stack
router.push(BooksListRoute())

// pops the last page unless stack has 1 entry
context.router.pop()


// pops until provided route, if it already exists in stack
// else adds it to the stack (good for web Apps).
router.navigate(BooksListRoute())

// replaces last entry in stack, throws an error if stack is empty
router.replace(BooksListRoute())

Passing Arguments


That's the fun part! AutoRoute automatically detects and handles your page arguments for your, the generated Route object will deliver all the arguments your page needs including callback functions (to return results).

e.g. The following page widget will take an argument of type Book and a callback function that returns a rating value on pop.

class BookDetailsPage extends StatelessWidget {
 const BookDetailsRoute({this.book, this.onRateBook});

  final Book book;
  final void Function(int) onRateBook;
  ...

Note: Default values are respected. Required fields are also respected and handled properly.

The generated BookDetailsRoute will deliver the same arguments to it's corresponding page.

context.router.push(
      BookDetailsRoute(
          book: book,
          onRateBook: (rating) {
           // handle result
          }),
    );

make sure you call the callback function as you pop the page

onRateBook?.call(RESULT);
context.router.pop();

Working with Paths

Working with paths in AutoRoute is optional because PageRouteInfo objects are matched by name unless pushed as a string using the initialDeepLink property in root delegate or pushPath method in StackRouter.

if you don’t specify a path it’s going to be generated from the page name e.g. BookListPage will have ‘book-list-page’ as a path, if initial arg is set to true the path will be / unless it's relative then it will be an empty string ''.

When developing a web Application or a native App that requires deep-linking you'd probably need to define paths with clear memorable names, and that's done using the path argument in AutoRoute.

 AutoRoute(path: '/books', page: BookListPage),

Path Parameters (dynamic segments)

You can define a dynamic segment by prefixing it with a colon

 AutoRoute(path: '/books/:id', page: BookDetailsPage),

if you define a path with a dynamic segment the corresponding page's constructor must have a parameter that is annotated with @PathParam('optional-alias') with the same alias/name of the segment.

class BookDetailsPage extends StatelessWidget {
  BookDetailsPage({@PathParam('id') this.bookId});

  final int bookId;
  ...

Now writing /books/1 in the browser will navigate you to BookDetailsPage and automatically extract the bookId argument from the path.

Query Parameters

Query parameters are accessed the same way, simply annotate the constructor parameter to hold the value of the query param with @QueryParam('optional-alias') and let AutoRoute do the rest.

you could also access path/query parameters using the scoped RouteData object.

 RouteData.of(context).pathParams;
 // or using the extension
 context.route.queryParams

Redirecting Paths

Paths can be redirected using RedirectRoute. The following setup will navigate us to /books when / is matched.

<AutoRoute> [
     RedirectRoute(path: '/', redirectTo: '/books'),
     AutoRoute(path: '/books', page: BookListPage),
 ]

Note: RedirectRoutes are fully matched.

Wildcards

AutoRoute supports wildcard matching to handle invalid or undefined paths.

AutoRoute(path: '*', page: UnknownRoutePage)
// it could be used with defined prefixes
AutoRoute(path: '/profile/*', page: ProfilePage)
// or it could be used with RedirectRoute
RedirectRoute(path: '*', redirectTo: '/')

Note: be sure to always add your wildcards at the end of your route list because routes are matched in order.

Nested Routes

Nesting routes with AutoRoute is as easy as populating the children field of the parent route. In the following example both UserProfilePage and UserPostsPage are nested children of UserPage.

@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(
      path: '/user/:id',
      page: UserPage,
      children: [
        AutoRoute(path: 'profile', page: UserProfilePage),
        AutoRoute(path: 'posts', page: UserPostsPage),
      ],
    ),
  ],
)
class $AppRouter {}

The parent page UserPage will be rendered inside of root router widget provided by MaterialApp.router but not its children, that's why we need to place an AutoRouter widget inside of UserPage where we need the nested routes to be rendered.

class UserPage extends StatelessWidget {
  const UserPage({Key key, @pathParam this.id}) : super(key: key);
  final int id;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('User $id')), 
      body: AutoRouter() // nested routes will be rendered here
    );
  }
}

Now if we navigate to /user/1 we will be presented with a page that has an appBar title that says User 1 and an empty body, why? because we haven't pushed any routes to our nested AutoRouter, but if we navigate to user/1/profile the UserProfilePage will be pushed to the nested router and that's what we will see.

What if want to show one of the child pages at /users/1? we can simply do that by giving the child page an empty path ''.

   AutoRoute(
      path: '/user/:id',
      page: UserPage,
      children: [
        AutoRoute(path: '', page: UserProfilePage),
        AutoRoute(path: 'posts', page: UserPostsPage),
      ],
    ),

or by using RedirectRoute

   AutoRoute(
      path: '/user/:id',
      page: UserPage,
      children: [
        RedirectRoute(path: '', redirectTo: 'profile'),
        AutoRoute(path: 'profile', page: UserProfilePage),
        AutoRoute(path: 'posts', page: UserPostsPage),
      ],
    ),

in both cases whenever we navigate to /user/1 we will be presented with the UserProfilePage.

Finding The Right Router

Every nested AutoRouter has its own routing controller to manage the stack inside of it and the easiest way to obtain a scoped controller is by using context.

In the previous example UserPage is a root level stack entry so calling AutoRouter.of(context) anywhere inside of it will get us the root routing controller.

AutoRouter widgets that are used to render nested routes insert a new router scope into the widgets tree, so when a nested route calls for the scoped controller they will get the closest parent controller in the widgets tree not the root controller.

class UserPage extends StatelessWidget {
  const UserPage({Key key, @pathParam this.id}) : super(key: key);
  final int id;
  @override
  Widget build(BuildContext context) {
  // this will get us the root routing controller
    AutoRouter.of(context);
    return Scaffold(
      appBar: AppBar(title: Text('User $id')), 
      // this inserts a new router scope into the widgets tree
      body: AutoRouter() 
    );
  }
}

Here's a simple diagram to help visualize this

As you can tell from the above diagram it's possible to access parent routing controllers by calling router.parent<T>(), we're using a generic function because we too different routing controllers StackRouter and TabsRouter, one of them could be the parent controller of the current router and that's why we need to specify a type.

router.parent<StackRouter>() // this returns a the parent router as a Stack Routing controller
router.parent<TabsRouter>() // this returns a the parent router as a Tabs Routing controller

on the other hand obtaining the root controller does not require type casting because it's always a StackRouter.

router.root // this returns the root router as a Stack Routing controller

You could also obtain inner-routers from outside their scope as long as you have access to the parent router.

// assuming this's the root router
AutoRouter.of(context).innerRouterOf<StackRouter>(UserRoute.name)
// or use the short version 
AutoRouter.innerRouterOf(context, UserRoute.name);

Accessing the UserPage inner router from the previous example.

class UserPage extends StatelessWidget {  
  final int id;  
  
  const UserPage({Key key, @pathParam this.id}) : super(key: key);  
  
  @override  
  Widget build(BuildContext context) {  
	  return Scaffold(  
		  appBar: AppBar(  
		  title: Text('User $id'),  
			  actions: [  
				  IconButton(  
					  icon: Icon(Icons.account_box),  
					  onPressed: () {  
					  // accessing the inner router from 
					  // outside the scope
					  AutoRouter.innerRouterOf(context, UserRoute.name)
					  .push(UserPostsRoute());  
					 },
				  ),
				], 
			 ), 
			  body: AutoRouter(), // we're trying to get access to this
		 ); 
	 }
 }

Note: nested routing controllers are created along with the parent route so accessing them without context is safe as long as it's somewhere beneath the parent route ( The host page ).

More docs are coming soon

Support auto_route

You can support auto_route by liking it on Pub and staring it on Github, sharing ideas on how we can enhance a certain functionality or by reporting any problems you encounter

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].