Viewing version 11.1.0. Open the latest package page.

auto_route

11.1.0

AutoRoute is a declarative routing solution, where everything needed for navigation is automatically generated for you.

Download archive

Readme


LeanBuilder support (Experimental) ⚡

auto_route_generator: (10.2.3+) now supports LeanBuilder for super-fast incremental builds.

to use lean_builder instead of build_runner, simply add it to your dev_dependencies:

dev_dependencies:
  auto_route_generator: <latest-version>
  lean_builder: <latest-version>

and then run the builder using: for one-time build

dart run lean_builder build

for watching files and rebuilding on changes

dart run lean_builder watch

to disable auto_route_generator from using build_runner, you can add the following to your build.yaml file:

targets:
  $default:
    builders:
      auto_route_generator:auto_route_generator:
        enabled: false
      auto_route_generator:auto_router_generator:
        enabled: false

Migration guides

Old documentation

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

Add the following dependencies to your pubspec.yaml file:

dependencies:
 auto_route: [latest-version]

dev_dependencies:
 auto_route_generator: [latest-version]
 build_runner:
flutter pub add auto_route dev:auto_route_generator dev:build_runner

Setup And Usage

  1. Create a router class and annotate it with @AutoRouterConfig then extend "RootStackRouter" from The auto_route package
  2. Override the routes getter and start adding your routes.
@AutoRouterConfig()
class AppRouter extends RootStackRouter {

  @override
  List<AutoRoute> get routes => [
    /// routes go here
  ];
}

Using part builder

To generate a part-of file simply add a part directive to your AppRouter.

Note: The deferredLoading functionality does not work with part-file setup.

Generating Routable pages

Routable pages are just simple everyday widgets annotated with @RoutePage() which allows them to be constructed by the router.

@RoutePage()
class HomeScreen extends StatefulWidget {}

Now simply run the generator

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

dart run build_runner watch

If you want the generator to run one time and exit, use

dart run build_runner build

Add the generated route to your routes list

@AutoRouterConfig(replaceInRouteName: 'Screen|Page,Route')
class AppRouter extends RootStackRouter {

  @override
  RouteType get defaultRouteType => RouteType.material(); //.cupertino, .adaptive ..etc

  @override
  List<AutoRoute> get routes => [
    // HomeScreen is generated as HomeRoute because
    // of the replaceInRouteName property
    AutoRoute(page: HomeRoute.page),
  ];

  @override
  List<AutoRouteGuard> get guards => [
    // optionally add root guards here
  ];
}

Finalize the setup

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

// assuming this is the root widget of your App
class App extends StatelessWidget {
  // make sure you don't initiate your router
  // inside of the build function.
  final _appRouter = AppRouter();

  @override
  Widget build(BuildContext context){
    return MaterialApp.router(
      routerConfig: _appRouter.config(),
    );
  }
}

Usage without code generation

You can use auto_route without code generation by providing an inline NamedRouteDef with a page builder function, as name suggests, you must provide a name for the route so you can navigate to it later by name or path.

Declaring Named Routes

  NamedRouteDef(
    name: 'BookDetailsRoute',
    path: '/books/:id', // optional
    builder: (context, data) {
      return BookDetailsPage(id: data.params.getInt('id'));
    },
  ),

NamedRouteDef is a wrapper around AutoRoute that allows you to provide a page builder function instead of a generated page, it has the same properties as AutoRoute except for page properties.

Tip: use the shorthand version of NamedRouteRef for a cleaner look

   routes: [
     .named('HomeRoute', (ctx, data) => HomePage()),
     .named('BookListRoute', (ctx, data) => BookListPage()),
    ];

Navigating to Named Routes

You can either navigate to a named route by using the dynamic NamedRoute class to match by name or by using the pushPath method to match by path.

 /// match by name
    router.push(NamedRoute('BookDetailsRoute', params: {'id': 1}));
    router.replace(NamedRoute('BookDetailsRoute', params: {'id': 1}));
    router.navigate(NamedRoute('BookDetailsRoute', params: {'id': 1}));
 /// or use the shorthand version
    router.push(.named('BookDetailsRoute',) params: {'id': 1}));
    
/// match by path
     router.pushPath('/books/1');
     router.replacePath('/books/1');
     router.navigatePath('/books/1');

Note: You can mix and match between named and generated routes.

Building a router without code generation

You can either extend RootStackRouter like you would normally do or use the RootStackRouter.build constructor to build a router without code generation.

    final router = RootStackRouter.build(
      defaultRouteType: ...,
      guards: [global guards],
      routes: [
        NamedRouteDef(
          name: 'BookDetailsRoute',
          path: '/books/:id', // optional
          builder: (context, data) {
            return BookDetailsPage(id: data.params.getInt('id'));
          },
        ),
         // ... other routes
      ],
    );

Generated Routes

A PageRouteInfo object will be generated for every declared AutoRoute. These objects hold strongly-typed page arguments which are extracted from the page's default constructor. Think of them as string path segments on steroids.

class BookListRoute extends PageRouteInfo {
  const BookListRoute({
    List<PagerouteInfo>? children,
  }) : super(name, initialChildren: children);

  static const String name = 'BookListRoute';
  static const PageInfo page = PageInfo(name,builder: (...));
}

Navigating Between Screens

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

// get the scoped router by calling
AutoRouter.of(context);
// or using the extension
context.router;
// adds a new entry to the pages stack
router.push(const BooksListRoute());
// or by using paths
router.pushPath('/books');
// removes last entry in stack and pushes provided route
// if last entry == provided route page will just be updated
router.replace(const BooksListRoute());
// or by using paths
router.replacePath('/books');
// pops until provided route, if it already exists in stack
// else adds it to the stack (good for web Apps).
router.navigate(const BooksListRoute());
// or by using paths
router.navigatePath('/books');
// on Web it calls window.history.back();
// on Native it navigates you back
// to the previous location
router.back();
// adds a list of routes to the pages stack at once
router.pushAll([
  BooksListRoute(),
  BookDetailsRoute(id: 1),
]);
// This is like providing a completely new stack as it rebuilds the stack
// with the list of passed routes
// entries might just update if already exist
router.replaceAll([
  LoginRoute(),
]);

// pops the top page even if it's the last entry in stack
context.router.pop()
// pops the most top page of the most top router even if it's the last entry in stack
context.router.popTop();

// pops the last page unless blocked or stack has only 1 entry
context.router.maybePop();
// pops the most top page of the most top router unless blocked
// or stack has only 1 entry
context.router.maybePopTop();
// keeps popping routes until predicate is satisfied
context.router.popUntil((route) => route.settings.name == 'HomeRoute');
// a simplified version of the above line
context.router.popUntilRouteWithName('HomeRoute');
// keeps popping routes until route with provided path is found
context.router.popUntilRouteWithPath('/some-path');
// pops all routes down to the root
context.router.popUntilRoot();
// removes the top most page in stack even if it's the last
// remove != pop, it doesn't respect WillPopScopes it just
// removes the entry.
context.router.removeLast();
// removes any route in stack that satisfies the predicate
// this works exactly like removing items from a regular List
// <PageRouteInfo>[...].removeWhere((r)=>)
context.router.removeWhere((route) => );
// you can also use the common helper methods from context extension to navigate
context.pushRoute(const BooksListRoute());
context.replaceRoute(const BooksListRoute());
context.navigateTo(const BooksListRoute());
context.navigateToPath('/books');
context.back();
context.maybePop();
context.pop();

Passing Arguments

That's the fun part! AutoRoute automatically detects and handles your page arguments for you, the generated route object will deliver all the arguments your page needs including path/query params.

e.g. The following page widget will take an argument of type Book.

@RoutePage()
class BookDetailsPage extends StatelessWidget {
  const BookDetailsPage({required this.book});

  final Book book;
  ...

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

The generated BookDetailsRoute will deliver the same arguments to its corresponding page.

router.push(BookDetailsRoute(book: book));

Note: All arguments are generated as named parameters regardless of their original type.

Returning Results

You can return results by either using the pop completer or by passing a callback function as an argument the same way you'd pass an object.

1. Using the pop completer

var result = await router.push(LoginRoute());

then inside of your LoginPage, pop with results

router.maybePop(true);

Specifying the type of the result is optional, but it's recommended to avoid runtime errors.

var result = await router.push<bool>(LoginRoute());

and of course we pop with the same type

router.maybePop<bool>(true);

2. Passing a callback function as an argument.

We only have to add a callback function as a parameter to our page constructor like follows:

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

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

The generated BookDetailsRoute will deliver the same arguments to its corresponding page.

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

If you're finishing with results, make sure you call the callback function as you pop the page

onRateBook(RESULT);
context.maybePop();

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

Nested Navigation

Nested navigation means building an inner router inside of a page of another router, for example in the below diagram users page is built inside of dashboard page.

Defining nested routes is as easy as populating the children field of the parent route. In the following example UsersPage, PostsPage and SettingsPage are nested children of DashboardPage.

@AutoRouterConfig(replaceInRouteName: 'Page,Route')
class AppRouter extends RootStackRouter {

@override
List<AutoRoute> get routes => [
    AutoRoute(
      path: '/dashboard',
      page: DashboardRoute.page,
      children: [
        AutoRoute(path: 'users', page: UsersRoute.page),
        AutoRoute(path: 'posts', page: PostsRoute.page),
        AutoRoute(path: 'settings', page: SettingsRoute.page),
      ],
    ),
    AutoRoute(path: '/login', page: LoginRoute.page),
  ];
}

To render/build nested routes we need an AutoRouter widget that works as an outlet or a nested router-view inside of our dashboard page.

class DashboardPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Column(
          children: [
            NavLink(label: 'Users', destination: const UsersRoute()),
            NavLink(label: 'Posts', destination: const PostsRoute()),
            NavLink(label: 'Settings', destination: const SettingsRoute()),
          ],
        ),
        Expanded(
          // nested routes will be rendered here
          child: AutoRouter(), // this is important
        ),
      ],
    );
  }
}

Note NavLink is just a button that calls router.push(destination). Now if we navigate to /dashboard/users, we will be taken to the DashboardPage and the UsersPage will be shown inside of it.

What if want to show one of the child pages at /dashboard? We can simply do that by giving the child routes an empty path '' to make initial or by setting initial to true.

AutoRoute(
  path: '/dashboard',
  page: DashboardRoute.page,
  children: [
    AutoRoute(path: '', page: UsersRoute.page),
    AutoRoute(path: 'posts', page: PostsRoute.page),
  ],
)

or by using a RedirectRoute

AutoRoute(
  path: '/dashboard',
  page: DashboardRoute.page,
  children: [
    RedirectRoute(path: '', redirectTo: 'users'),
    AutoRoute(path: 'users', page: UsersRoute.page),
    AutoRoute(path: 'posts', page: PostsRoute.page),
  ],
)

Creating Empty Shell routes

Empty shell routes build a screen that contain the AutoRouter widget, which is used to render nested routes. So you can build the widget your self like follows:

@RoutePage()
class MyShellPage extends StatelessWidget {
  const MyShellPage({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
     /// you can wrap the AutoRouter with any widget you want
    return  AutoRouter();
  }
}

You can shorten the code above a bit by directly extending the AutoRouter Widget.

@RoutePage()
class MyShellPage extends AutoRouter {
   const MyShellPage({Key? key}) : super(key: key);
}

finally you can create a shell route without code generation using the EmptyShellRoute helper

   const BooksTab = EmptyShellRoute('BooksTab');
   context.push(BooksTab());

Things to keep in mind when implementing nested navigation

  1. Each router manages its own pages stack.
  2. Navigation actions like push, pop and friends are handled by the topmost router and bubble up if it couldn't be handled.

Tab Navigation

If you're working with flutter mobile, you're most likely to implement tabs navigation, that's why auto_route makes tabs navigation as easy and straightforward as possible.

In the previous example we used an AutoRouter widget to render nested child routes, AutoRouter is just a shortcut for AutoStackRouter. StackRouters manage a stack of pages inside of them, where the active/visible page is always the one on top and you'd need to pop it to see the page beneath it.

Now we can try to implement our tabs using an AutoRouter (StackRouter) by pushing or replacing a nested route every time the tab changes and that might work, but our tabs state will be lost, not to mention the transition between tabs issue, luckily auto_route comes equipped with an AutoTabsRouter, which is especially made to handle tab navigation.

AutoTabsRouter lets you switch between different routes while preserving offstage-routes state, tab routes are lazily loaded by default (can be disabled) and it finally allows to create whatever transition animation you want.

Let's change the previous example to use tab navigation.

Notice that we're not going to change anything in our routes declaration map, we still have a dashboard page that has three nested children: users, posts and settings.

class DashboardPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return AutoTabsRouter(
      // list of your tab routes
      // routes used here must be declared as children
      // routes of /dashboard
      routes: const [
        UsersRoute(),
        PostsRoute(),
        SettingsRoute(),
      ],
      transitionBuilder: (context,child,animation) => FadeTransition(
            opacity: animation,
            // the passed child is technically our animated selected-tab page
            child: child,
          ),
      builder: (context, child) {
        // obtain the scoped TabsRouter controller using context
        final tabsRouter = AutoTabsRouter.of(context);
        // Here we're building our Scaffold inside of AutoTabsRouter
        // to access the tabsRouter controller provided in this context
        //
        // alternatively, you could use a global key
        return Scaffold(
          body: child,
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: tabsRouter.activeIndex,
            onTap: (index) {
              // here we switch between tabs
              tabsRouter.setActiveIndex(index);
            },
            items: [
              BottomNavigationBarItem(label: 'Users', ...),
              BottomNavigationBarItem(label: 'Posts', ...),
              BottomNavigationBarItem(label: 'Settings', ...),
            ],
          ),
        );
      },
    );
  }
}

If you think the above setup is a bit messy you could use the shipped-in AutoTabsScaffold that makes things much cleaner.

class DashboardPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AutoTabsScaffold(
      routes: const [
        UsersRoute(),
        PostsRoute(),
        SettingsRoute(),
      ],
      bottomNavigationBuilder: (_, tabsRouter) {
        return BottomNavigationBar(
          currentIndex: tabsRouter.activeIndex,
          onTap: tabsRouter.setActiveIndex,
          items: const [
            BottomNavigationBarItem(label: 'Users', ...),
            BottomNavigationBarItem(label: 'Posts', ...),
            BottomNavigationBarItem(label: 'Settings', ...),
          ],
        );
      },
    );
  }
}

Using PageView

Use the AutoTabsRouter.pageView constructor to implement tabs using PageView

AutoTabsRouter.pageView(
  routes: [
    BooksTab(),
    ProfileTab(),
    SettingsTab(),
  ],
  builder: (context, child, _) {
    final tabsRouter = AutoTabsRouter.of(context);
    return Scaffold(
      appBar: AppBar(
        title: Text(context.topRoute.name),
        leading: AutoLeadingButton(),
      ),
      body: child,
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: tabsRouter.activeIndex,
        onTap: tabsRouter.setActiveIndex,
        items: [
          BottomNavigationBarItem(label: 'Books', ...),
          BottomNavigationBarItem(label: 'Profile', ...),
          BottomNavigationBarItem(label: 'Settings', ...),
        ],
      ),
    );
  },
);

Using TabBar

Use the AutoTabsRouter.tabBar constructor to implement tabs using TabBar

AutoTabsRouter.tabBar(
  routes: [
    BooksTab(),
    ProfileTab(),
    SettingsTab(),
  ],
  builder: (context, child, controller) {
    final tabsRouter = AutoTabsRouter.of(context);
    return Scaffold(
      appBar: AppBar(
        title: Text(context.topRoute.name),
        leading: AutoLeadingButton(),
        bottom: TabBar(
          controller: controller,
          tabs: const [
            Tab(text: '1', icon: Icon(Icons.abc)),
            Tab(text: '2', icon: Icon(Icons.abc)),
            Tab(text: '3', icon: Icon(Icons.abc)),
          ],
        ),
      ),
      body: child,
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: tabsRouter.activeIndex,
        onTap: tabsRouter.setActiveIndex,
        items: [
          BottomNavigationBarItem(label: 'Books',...),
          BottomNavigationBarItem(label: 'Profile',...),
          BottomNavigationBarItem(label: 'Settings',...),
        ],
      ),
    );
  },
);

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 the BuildContext.

In the previous example, DashboardPage 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 Dashboard extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // this will get us the root routing controller
    AutoRouter.of(context);
    return Scaffold(
      appBar: AppBar(title: Text('Dashboard page')),
      // 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 have two 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  the parent router as a Stack Routing controller
router.parent<TabsRouter>() // this returns 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 can obtain access to inner-routers from outside their scope using a global key

class DashboardPage extends StatefulWidget {
  @override
  _DashboardPageState createState() => _DashboardPageState();
}

class _DashboardPageState extends State<DashboardPage> {
  final _innerRouterKey = GlobalKey<AutoRouterState>();

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Column(
          children: [
            NavLink(
              label: 'Users',
              onTap: () {
                final router = _innerRouterKey.currentState?.controller;
                router?.push(const UsersRoute());
              },
            ),
            ...
          ],
        ),
        Expanded(
          child: AutoRouter(key: _innerRouterKey),
        ),
      ],
    );
  }
}

You could also obtain access to inner-routers from outside their scope without a global key, as long as they're initiated.

// assuming this is the root router
context.innerRouterOf<StackRouter>(UserRoute.name);
// or if we're using an AutoTabsRouter inside of DashboardPage
context.innerRouterOf<TabsRouter>(UserRoute.name);

Accessing the DashboardPage inner router from the previous example.

class Dashboard extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dashboard'),
        actions: [
          IconButton(
            icon: Icon(Icons.person),
            onPressed: () {
              // accessing the inner router from
              // outside the scope
              final router = context.innerRouterOf<StackRouter>(DashboardRoute.name)
              router?.push(const UsersRoute());
            },
          ),
        ],
      ),
      body: AutoRouter(), // we're trying to get access to this
    );
  }
}

Navigating Without Context

To navigate without context you can simply assign your generated router to a global variable

// declare your route as a global variable
final appRouter = AppRouter();

class MyApp extends StatefulWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: appRouter.config(),
    );
  }
}

Note: Using global variable is not recommended and is considered bad practice and most of the times you should use dependency injection instead.

Here's an example using get_it (which is just a personal favorite). You can use any dependency injection package you like.

void main(){
  // make sure you register it as a Singleton or a lazySingleton
  getIt.registerSingleton<AppRouter>(AppRouter());
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  Widget build(BuildContext context) {
    final appRouter = getIt<AppRouter>();

    return MaterialApp.router(
      routerConfig: appRouter.config(),
    );
  }
}

Now you can access your router anywhere inside of your app without using context.

getIt<AppRouter>().push(...);

Note: Navigating without context is not recommended in nested navigation unless you use navigate instead of push and you provide a full hierarchy, e.g router.navigate(SecondRoute(children: [SubChild2Route()]))

Deep Linking

AutoRoute will automatically handle deep-links coming from the platform, but native platforms require some setup, see Deep linking topic in flutter documentation.

Using Deep-link Transformer

Deep link transformer intercepts deep-links before they're processed by the matcher, it's useful for stripping or modifying deep-links before they're matched.

In the following example we will strip a prefix from the deep-link before it's matched.

MaterialApp.router(
  routerConfig: _appRouter.config(
    deepLinkTransformer: (uri) {
      if (uri.path.startsWith('/prefix')) {
        return SynchronousFuture(
        uri.replace(path: uri.path.replaceFirst('/prefix', '')),
          );
      }
      return SynchronousFuture(uri);
    }
  ),
);

Note for prefix stripping use the shipped-in DeepLink.prefixStripper('prefix')

MaterialApp.router(
  routerConfig: _appRouter.config(
    deepLinkTransformer: DeepLink.prefixStripper('prefix'),
  ),
);

Using Deep-link Builder

Deep link builder is an interceptor for deep-links where you can validate or override deep-links coming from the platform.

In the following example we will only allow deep-links starting with /products

MaterialApp.router(
  routerConfig: _appRouter.config(
    deepLinkBuilder: (deepLink) {
      if (deepLink.path.startsWith('/products')) {
        // continue with the platform link
        return deepLink;
      } else {
        return DeepLink.defaultPath;
        // or DeepLink.path('/')
        // or DeepLink([HomeRoute()])
      }
    }
  ),
);

Deep Linking to non-nested Routes

AutoRoute can build a stack from a linear route list as long as they're ordered properly and can be matched as prefix, e.g / is a prefix match of /products, and /products is prefix match of /products/:id. Then we have a setup that looks something like this:

  • /
  • /products
  • /products/:id

Now, receiving this deep-link /products/123 will add all above routes to the stack. This of course requires includePrefixMatches to be true in the root config (default is !kWeb) or when using pushNamed, navigateNamed and replaceNamed.

Things to keep in mind:

  • If a full match can not finally be found, no prefix matches will be included.
  • Paths that require a full path match => AutoRoute(path:'path', fullMatch: true) will not be included as prefix matches.
  • In the above example, if /products/:id comes before /products, /products will not be included.

Declarative Navigation

To use declarative navigation with auto_route, you simply use the AutoRouter.declarative constructor and return a list of routes based on state.

AutoRouter.declarative(
  routes: (handler) => [
    BookListRoute(),
    if(_selectedBook != null) {
      BookDetailsRoute(id: _selectedBook.id),
    }
  ],
);

Note: The handler contains a temp-list of pending initial routes which can be read only once.

Working with Paths

Working with paths in AutoRoute is optional because PageRouteInfo objects are matched by name unless pushed as a string using the deepLinkBuilder property in root delegate or pushNamed, replaceNamed navigateNamed methods.

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),

The simplest way to extract path parameters from path and gain access to them is by annotating constructor params with @PathParam('optional-alias') with the same alias/name of the segment.

class BookDetailsPage extends StatelessWidget {
  const 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 path and inject it to your widget.

Inherited Path Parameters

To inherit a path-parameter from a parent route's path, we need to use @PathParam.inherit annotation in the child route's constructor. Let's say we have the following setup:

AutoRoute(
  path: '/product/:id',
  page: ProductRoute.page,
  children: [
    AutoRoute(path: 'review',page: ProductReviewRoute.page),
  ],
)

Now ProductReviewScreen expects a path-param named id but, from the above snippet we know that the path corresponding with it. review has no path parameters, but we can inherit 'id' from the parent /product/:id like follows:

@RoutePage()
class ProductReviewScreen extends StatelessWidget {
  // the path-param 'id' will be inherited and it can not be passed
  // as a route arg by user
  const ProductReviewScreen({super.key, @PathParam.inherit('id') required String id});
}

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.routeData.queryParams;

Tip: if your parameter name is the same as the path/query parameter, you could use the const @pathParam or @queryParam and not pass a slug/alias.

@RoutePage()
class BookDetailsPage extends StatelessWidget {
  const BookDetailsPage({@pathParam this.id});

  final int id;
  ...
}

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: BookListRoute.page),
]

When redirecting initial routes the above setup can be simplified by setting the /books path as initial and AutoRoute will automatically generate the required redirect code for you.

<AutoRoute> [
  AutoRoute(path: '/books', page: BookListRoute.page, initial: true),
]

You can also redirect paths with params like follows:

<AutoRoute> [
  RedirectRoute(path: 'books/:id', redirectTo: '/books/:id/details'),
  AutoRoute(path: '/books/:id/details', page: BookDetailsRoute.page),
]

Note: RedirectRoutes are fully matched.

Wildcards

AutoRoute supports wildcard matching to handle invalid or undefined paths.

AutoRoute(
  path: '*',
  page: UnknownRoute.page,
)
// it could be used with defined prefixes
AutoRoute(
  path: '/profile/*',
  page: ProfileRoute.page,
)
// 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.

Route Guards

Think of route guards as middleware or interceptors, routes can not be added to the stack without going through their assigned guards. Guards are useful for restricting access to certain routes.

We create a route guard by extending AutoRouteGuard from the AutoRoute package and implementing our logic inside of the onNavigation method.

class AuthGuard extends AutoRouteGuard {

  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) {
    // the navigation is paused until resolver.next() is called with either
    // true to resume/continue navigation or false to abort navigation
    if(authenticated) {
      // if user is authenticated we continue
      resolver.next(true);
    } else {
        // we redirect the user to our login page
        // tip: use resolver.redirectUntil to have the redirected route
        // automatically removed from the stack when the resolver is completed
        resolver.redirectUntil(
          LoginRoute(onResult: (success) {
            // if success == true the navigation will be resumed
            // else it will be aborted
            resolver.next(success);
          },
        );
      );
    }
  }
}

Important: resolver.next() should only be called once.

The NavigationResolver object contains the guarded route which you can access by calling the property resolver.route and a list of pending routes (if there are any) accessed by calling resolver.pendingRoutes.

Now we assign our guard to the routes we want to protect.

AutoRoute(
  page: ProfileRoute.page,
  guards: [AuthGuard()],
);

Guarding all stack-routes

You can have all your stack-routes (non-tab-routes) go through a list of global guards by overriding the guards property inside your router class. Lets say you have an app with no public screens, we'd have a global guard that only allows navigation if the user is authenticated or if we're navigating to the LoginRoute.

@AutoRouterConfig()
class AppRouter extends RootStackRouter{

  @override
  late final List<AutoRouteGuard> guards = [
    AutoRouteGuard.simple((resolver, router) {
        if(isAuthenticated || resolver.routeName == LoginRoute.name) {
          // we continue navigation
          resolver.next();
        } else {
          // else we navigate to the Login page so we get authenticated

          // tip: use resolver.redirectUntil to have the redirected route
          // automatically removed from the stack when the resolver is completed
          resolver.redirectUntil(LoginRoute(onResult: (didLogin) => resolver.next(didLogin)));
        }
      },
    ),
    // add more guards here
  ];

// ..routes[]
}

Using a Reevaluate Listenable

Route guards can prevent users from accessing private pages until they're logged in, but auth state may change when the user is already navigated to the private page, to make sure private pages are only accessed by logged-in users all the time, we need a listenable that tells the router that the auth state has changed and you need to re-evaluate your stack.

The following auth provider mock will act as our re-valuate listenable

class AuthProvider extends ChangeNotifier {
  bool _isLoggedIn = false;

  bool get isLoggedIn => _isLoggedIn;

  void login() {
    _isLoggedIn = true;
    notifyListeners();
  }

  void logout() {
    _isLoggedIn = false;
    notifyListeners();
  }
}

We simply pass an instance of our AuthProvider to reevaluateListenable inside of router.config

MaterialApp.router(
  routerConfig: _appRouter.config(
    reevaluateListenable: authProvider,
  ),
);

Now, every time AuthProvider notifies listeners, the stack will be re-evaluated and AutoRouteGuard.onNavigation(). Methods will be re-called on all guards

In the above example, we assigned our AuthProvider to reevaluateListenable directly, that's because reevaluateListenable takes a Listenable and AuthProvider extends ChangeNotifier which is a Listenable, if your auth provider is a stream you can use reevaluateListenable: ReevaluateListenable.stream(YOUR-STREAM)

Note: When the Stack is re-evaluated, the whole existing hierarchy will be re-pushed, so if you want to stop re-evaluating routes at some point, use resolver.resolveNext(<options>) which is like resolver.next() but with more options.

@override
void onNavigation(NavigationResolver resolver, StackRouter router) async {
  if (authProvider.isAuthenticated) {
    resolver.next();
  } else {
    resolver.redirectUntil(
      WebLoginRoute(
        /// this part is optional if you're not using reevaluateListenable as this method will 
        /// be called again and if the condition is satisfied the resolver will be completed
        onResult: (didLogin) {
          /// stop re-pushing any pending routes after current
          resolver.resolveNext(didLogin, reevaluateNext: false);
        },
      ),
    );
  }
}

Wrapping Routes

In some cases we want to wrap our screen with a parent widget, usually to provide some values through context, e.g wrapping your route with a custom Theme or a Provider. To do that, simply implement AutoRouteWrapper, and have wrappedRoute(context) method return (this) as the child of your wrapper widget.

@RoutePage()
class ProductsScreen extends StatelessWidget implements AutoRouteWrapper {

  @override
  Widget wrappedRoute(BuildContext context) {
    return Provider(create: (ctx) => ProductsBloc(), child: this);
  }
  ...
}

Navigation Observers

Navigation observers are used to observe when routes are pushed ,replaced or popped ..etc.

We implement an AutoRouter observer by extending an AutoRouterObserver which is just a NavigatorObserver with tab route support.

class MyObserver extends AutoRouterObserver {

  @override
  void didPush(Route route, Route? previousRoute) {
    print('New route pushed: ${route.settings.name}');
  }

 // only override to observer tab routes
  @override
  void didInitTabRoute(TabPageRoute route, TabPageRoute? previousRoute) {
    print('Tab route visited: ${route.name}');
  }

  @override
  void didChangeTabRoute(TabPageRoute route, TabPageRoute previousRoute) {
    print('Tab route re-visited: ${route.name}');
  }
}

Then we pass our observer to the <routerName>.config(). Important: Notice that navigatorObservers property is a builder function that returns a list of observers and the reason for that is a navigator observer instance can only be used by a single router, so unless you're using a single router or you don't want your nested routers to inherit observers, make sure navigatorObservers builder always returns fresh observer instances.

return MaterialApp.router(
  routerConfig: _appRouter.config(
    navigatorObservers: () => [MyObserver()],
  ),
);

The following approach won't work if you have nested routers unless they don't inherit the observers.

final _observer = MyObserver();
return MaterialApp.router(
  routerConfig: _appRouter.config(
    // this should always return new instances
    navigatorObservers: () => [_observer],
  ),
);

Every nested router can have it's own observers and inherit it's parent's.

AutoRouter(
  inheritNavigatorObservers: true, // true by default
  navigatorObservers:() => [list of observers],
);

AutoTabsRouter(
  inheritNavigatorObservers: true, // true by default
  navigatorObservers:() => [list of observers],
);

We can also make a certain screen route aware by subscribing to an AutoRouteObserver (route not router).

First we provide our AutoRouteObserver instance

return MaterialApp.router(
  routerConfig: _appRouter.config(
    navigatorObservers: () => [AutoRouteObserver()],
  ),
);

Next, we use an AutoRouteAware mixin which is a RouteAware mixin with tab support to provide the needed listeners, then subscribe to our AutoRouteObserver.

class BooksListPage extends State<BookListPage> with AutoRouteAware {
  AutoRouteObserver? _observer;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // RouterScope exposes the list of provided observers
    // including inherited observers
    _observer = RouterScope.of(context).firstObserverOfType<AutoRouteObserver>();
    if (_observer != null) {
      // we subscribe to the observer by passing our
      // AutoRouteAware state and the scoped routeData
      _observer.subscribe(this, context.routeData);
    }
  }

 @override
  void dispose() {
    super.dispose();
    // don't forget to unsubscribe from the
    // observer on dispose
    _observer.unsubscribe(this);
  }

  // only override if this is a tab page
  @override
  void didInitTabRoute(TabPageRoute? previousRoute) {}

  // only override if this is a tab page
  @override
  void didChangeTabRoute(TabPageRoute previousRoute) {}

  @override
  void didPopNext() {}

  @override
  void didPushNext() {}

  @override
  void didPush() {}

  @override
  void didPop() {}
}

AutoRouteAwareStateMixin

The above code can be simplified using AutoRouteAwareStateMixin

class BooksListPage extends State<BookListPage> with AutoRouteAwareStateMixin<BookListPage> {
  // only override if this is a tab page
  @override
  void didInitTabRoute(TabPageRoute? previousRoute) {}

  // only override if this is a tab page
  @override
  void didChangeTabRoute(TabPageRoute previousRoute) {}

  // only override if this is a stack page
  @override
  void didPopNext() {}

  // only override if this is a stack page
  @override
  void didPushNext() {}
}

Customizations

MaterialAutoRouter | CupertinoAutoRouter | AdaptiveAutoRouter
Property Default value Definition
replaceInRouteName [String] Page&#124Screen,Route Used to replace conventional words in generated route name (pattern, replacement)

Custom Route Transitions

To use custom route transitions use a CustomRoute and pass in your preferences. The TransitionsBuilder function needs to be passed as a static/const reference that has the same signature as the TransitionsBuilder function of the PageRouteBuilder class.

CustomRoute(
  page: LoginRoute.page,
  // TransitionsBuilders class contains a preset of common transitions builders.
  transitionsBuilder: TransitionsBuilders.slideBottom,
  duration: Duration(milliseconds: 400),
)

Tip: Override defaultRouteType in generated router to define global custom route transitions.

You can of course use your own transitionsBuilder function, as long as it has the same function signature. The function has to take in exactly one BuildContext, Animation<Double>, Animation<Double> and a child Widget and it needs to return a Widget. Typically, you would wrap your child with one of Flutter's transition widgets as follows:

CustomRoute(
  page: ZoomInScreen,
  transitionsBuilder:
    (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
      // you get an animation object and a widget
      // make your own transition
      return ScaleTransition(scale: animation, child: child);
  },
)

Custom Route Builder

You can use your own custom route by passing a CustomRouteBuilder function to `CustomRoute' and implement the builder function the same way we did with the TransitionsBuilder function, the most important part here is passing the page argument to our custom route.

make sure you pass the return type to your custom route builder function.

CustomRoute(
  page: CustomPage,
  customRouteBuilder: <T>(BuildContext context, Widget child, AutoRoutePage<T> page) {
    return PageRouteBuilder<T>(
      fullscreenDialog: page.fullscreenDialog,
      // this is important
      settings: page,
      pageBuilder: (_,__,___) => child,
    );
  },
)

Others

Including Micro/External Packages

To include routes inside of a depended-on package, we generated the routes inside the micro package like normal, then either use the generated routes inside your main router individually, or declare them inside your micro router and merge them with the main router.

  final myMicroRouter = MyMicroRouter();

  @override
  List<AutoRoute> get routes => [
        AutoRoute(page: HomeRoute.page, initial: true),
        /// use micro routes individually
        AutoRoute(page: RouteFromMicroPackage.page),
        /// or merge all routes from micro router
        ...myMicroRouter.routes,
      ];

Tip: You can add export MyMicroRouter to app_router.dart, so you only import app_router.dart inside of your code.

// ...imports
export 'package:my_package/my_micro_router.dart'
@AutoRouterConfig()
class AppRouter extends RootStackRouter {}

Configuring builders

To pass builder configuration to auto_route_generator we need to add build.yaml file next to pubspec.yaml if not already added.

targets:
  $default:
    builders:
      auto_route_generator:auto_route_generator:
      # configs for @RoutePage() generator ...
      auto_route_generator:auto_router_generator:
      # configs for @AutoRouterConfig() generator ...

Passing custom ignore_for_file rules

You can pass custom ignore_for_file rules to the generated router by adding the following:

targets:
  $default:
    builders:
      auto_route_generator:auto_router_generator:
       options:
         ignore_fore_file:
           - custom_rule_1
           - custom_rule_2

Optimizing generation time

The first thing you want to do to reduce generation time, is specifying the files build_runner should process and we do that by using globs. Globs are kind of regex patterns with little differences that's used to match file names. Note: for this to work on file level you need to follow a naming convention

let's say we have the following files tree
├── lib
│ ├── none_widget_file.dart
│ ├── none_widget_file2.dart
│ └── ui
│ ├── products_screen.dart
│ ├── products_details_screen.dart

By default, the builder will process all of these files to check for a page with @RoutePage() annotation, we can help by letting it know what files we need processed, e.g only process the files inside the ui folder: Note (**) matches everything including '/';

targets:
  $default:
    builders:
      auto_route_generator:auto_route_generator:
        generate_for:
          - lib/ui/**.dart

Let's say you have widget files inside of the ui folder, but we only need to process files ending with _screen.dart

targets:
  $default:
    builders:
      auto_route_generator:auto_route_generator:
        generate_for:
          - lib/ui/**_screen.dart

Now only products_screen.dart, products_details_screen.dart will be processed

The same goes for @AutoRouterConfig builder

targets:
  $default:
    builders:
      auto_route_generator:auto_route_generator: # this for @RoutePage
        generate_for:
          - lib/ui/**_screen.dart
      auto_route_generator:auto_router_generator: # this for @AutoRouterConfig
        generate_for:
          - lib/ui/router.dart

Enabling cached builds

This is still experimental When cached builds are enabled, AutoRoute will try to prevent redundant re-builds by analyzing whether the file changes has any effect on the extracted route info, e.g any changes inside of the build method should be ignored.

Note Enable cached builds on both generators

targets:
  $default:
    builders:
      auto_route_generator:auto_route_generator: # this for @RoutePage
        options:
          enable_cached_builds: true
        generate_for:
          - lib/ui/**_screen.dart
      auto_route_generator:auto_router_generator: # this for @AutoRouterConfig
        options:
          enable_cached_builds: true
        generate_for:
          - lib/ui/router.dart

AutoLeadingButton-BackButton

AutoLeadingButton is AutoRoute's replacement to the default BackButton to handle nested or parent stack popping. To use it, simply assign it to the leading property inside of AppBar

AppBar(
  title: Text(context.topRoute.name),
  leading: AutoLeadingButton(),
)

you can also use AutoBackButton.builder above your Scaffold for example to provide a nullable leading widget to prevent AppBar.leadingWidth when there's no leading to show

AutoBackButton.builder(
  builder: (BuildContext context, Widget? leading) {
    return  Scaffold(
      appBar: AppBar(
        title: Text(context.topRoute.name),
        leading: leading,
      ),
    );
  },
)

ActiveGuardObserver

ActiveGuardObserver can notify you when a guard is being checked and what guard it is. This can be used to implement a loading indicator for example.

var isLoading = false;
void initState(){
  final guardObserver = context.router.activeGuardObserver;

  guardObserver.addListener(() {
    setState((){
      isLoading = guardObserver.guardInProgress;
    });
  });
}

Android Predictive Back

auto_route v10 supports Android predictive back, which is a feature that allows the user to take a peek at the previous route by swiping from the edge of the screen before committing to the back action.

For now this feature needs to be enabled in manifest file, it also has some flutter considerations, see Android Predictive Back for more information.

after you've enabled the feature in your manifest file, you can simply create predictive-back enabled routes by setting enablePredictiveBackGesture to true in your route type, you can also provide a custom predictiveBackPageTransitionsBuilder to customize the transitions.

  RouteType.material(
      enablePredictiveBackGesture: true,
       // optionally provide a custom transitions builder
      predictiveBackPageTransitionsBuilder: (context,animation,secondaryAnimation,child) {
       // return preferred transitions
      },
    )

you can enable predictive back for all routes by overriding defaultRouteType in your router, all route types that apply on android support this feature.

Examples

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 and of course buying a couple coffees will help speed up the development process

Changelog

11.1.0

  • CHORE: deprecate animatePageTransition #2301
  • Enhance: add .named constructor to PageRouteInfo and AutoRoute to enable usage for shorthand named routes without code generation.

11.0.0 [Breaking Changes]

  • BREAKING CHANGE: The redirectUntil method now returns void instead of Future<T?> and handles the completion of the pop completer internally
  • BREAKING CHANGE: The redirect method in AutoRouteGuard has been renamed to redirectUntil to better reflect its behavior and avoid confusion
  • BREAKING CHANGE: Removed deprecated APIs: navigateNamed, popForced, replaceNamed, pushNamed, and navigateNamedTo. Use navigatePath, pop, replacePath, pushPath instead

10.3.0

  • FEAT: Correct back-navigation behavior with proper state tracking
  • FEAT: Add async support and debug labels to AutoRouteGuard
  • FEAT: Add checkGuard method to NavigationResolver for sequential guard execution
  • FEAT: Implement comprehensive navigation history tracking with proper state management
  • FEAT: Prevent duplicate consecutive entries in navigation history

10.2.3

  • REFACTOR: Preserve match ID on route updates to prevent breaking child controllers during route updates or when replacing a route, fixes #2294
  • FIX: AutoTabsRouter.tabBar: Switching non-adjacent tabs shows the initial tab briefly when tapping a tab then swiping, instead of the tab you're swiping toward, fixes #2283
  • REFACTOR: Simplify PagelessRoutesObserver and address pop flicker by using the more efficient didChangeTop callback

10.2.2

  • FIX: known predictive back gesture issues.
  • FIX: add meta import to routing_controller.dart because some flutter versions require it.

10.2.1

  • FIX: correctly handle parameter names by removing leading underscores
  • Enhance: appBarBuilder in AutoTabsScaffold can return null now
  • FIX: Fix WASM type mismatch.

10.2.0

  • FIX: respect page.opaque for transparent route.
  • FIX: handle dart:xxx.xxx.dart imports in type resolution (af60d79) when using lean_builder
  • REFACTOR: introduce _genericRef function for improved type reference handling (d5ecf13)
  • FIX: respect page.opaque for transparent route (52b71b7)
  • FIX: Use immutable array for pending child routes, fixes #2210 (beb3ce0)
  • CHORE:: extend support to analyzer 8 (b2cb61d)

10.1.2

  • FIX: routing_controller.dart missing meta import

10.1.1

  • CHORE: tidy up dependencies and sync with updated analyzer version.
  • FIX: Add indexed stack semantics
  • FIX: Allow PopCompleter to complete during route reevaluation when pop-completers are disabled

10.1.0+1

  • FEAT: Add experimental support for lean_builder

10.1.0

  • FEAT: Expose routeTraversalEdgeBehavior property from the underlying Navigator to allow customization of navigation stack edge behavior.
  • FIX: Improve focus and semantics handling in AutoTabsRouter IndexedStack to exclude inactive tabs from focus traversal and semantics tree while preserving widget state.
  • FIX: Fix tab routes observing issue where initiating tabs can be reported twice.
  • FIX: Fix a couple core reevaluation issues.
  • FIX: Generated code is not properly formatted #2174
  • FIX: Fixed PageRouteInfo equality check regression introduced in v10.0.1 when using code generation with argsEquality: false, which now defaults to true. The equality operator no longer compares args by default unless argsEquality: true is explicitly set in AutoRouterConfig. This restores compatibility with previous versions and prevents navigation test failures due to custom argument classes lacking a proper == override.

10.0.1

  • REFACTOR(custom_route): update route duration type from int to Duration.
  • FEAT: add onGeneratePath callback to RootStackRouter to allow custom path generation.

10.0.0 [Minor Breaking Changes]

  • BREAKING CHANGE: DeepLink and DeepLink.path will now use 'navigate' instead of push unless specified
  • BREAKING CHANGE: ActiveGuardObserver.value will now return a GuardEntry instead of an AutoRouteGuard, use 'activeGuards' to get the list of active guards
  • FEAT: add support for using auto_route with out code generation using NamedRouteDef and NamedRoute otherwise.
  • FEAT: add support for android's predictive back gesture
  • FEAT: optional args equality by setting AutoRouterConfig(argsEquality: true)
  • FEAT: insert route method to StackRouter
  • FIX: guard reevaluation was re-implemented to fix previous issues
  • FEAT: expose Navigator.clipBehavior in both AutoRouterDelegate and AutoRouter
  • FIX: using AutoTabsRouter.tabBar with maintainState: false and TabBar together, fails to load routes in some cases #2113
  • FEAT: safe build context can now be accessed in AutoRouteGuard.onNavigation -> NavigationResolver.context
  • FEAT: add a new way to override guarded routes using NavigationResolver.overrideNext
  • FIX: AutoLeadingButton is not showing anything on a screen that combines AutoTabsScaffold and NestedRoute #2141
  • FIX: redirect route doesn't pass query params the to redirectTo path
  • FIX: generated PageRouteInfo breaks if widget tagged with @RoutePage parameter named children. #2149
  • FEAT: add an AutoLeadingButton.builder to enable passing of nullable leading widget
  • FIX: Fix a couple internal issues and migrate to using didRemovePage api
  • FEAT: Parameters.getList now supports a default value
  • FIX: Add required keyword to named required parameters in function parameters' arguments
  • FIX: fix inheritPathParam didn't use the .inherit constructor
  • REFACTOR rename a couple of apis (popForced -> pop, pushNamed -> pushPath, replaceNamed -> replacePath, navigateNamed -> navigatePath, pathParams -> params)

9.3.0+1

  • CHORE: Fix some static analysis warnings

9.3.0

  • CHORE: Resolve some deprecated APIs.

9.2.2

  • FIX: Redirect route names are getting overridden in route collection.

9.2.1+1

No changes, changelog fix only.

9.2.1

  • CHORE: Update web package to 1.0.0

9.2.0

  • FIX: revert web package back to version ^0.5.1 because it's pinned in a lot of other packages.

9.1.0

  • FEAT: Add query params options to redirectTo in RedirectRoute #1721.

9.0.1

  • FIX: make EmptyShellRoute() a const.
  • Chore: Add Declarative navigation example link
  • Chore: Add Nested Navigation example link

9.0.0 [Breaking Changes]

  • BREAKING CHANGE: No Router class will be generated anymore. Instead, you extend RootStackRouter from the auto_route package.
  • BREAKING CHANGE: Providing return types inside @RoutePage<Type>() is no longer needed. you just provide the type as you push the page.
  • BREAKING CHANGE: Providing a global route is now done by overriding the guards property inside the router. implementing AutoRouteGuard is no longer supported.
  • BREAKING CHANGE: AutoRouterConfig.module is removed as it's no longer needed. PageRouteInfos are now self-contained.

For more info read the complete migration guide Migrating to v9

  • FIX: Fix Aliased types are not generated correctly.
  • FEAT: You can now create empty shell routes like follows:
       const BooksTab = EmptyShellRoute('BooksTab');
       context.push(BooksTab());
    

8.3.0

  • FEAT: add url#fragment support.
  • FIX: queryParams are not passed to child routes when matching by route name
  • FIX: array query params are not parsed correctly.

8.2.0

  • FEAT: migrate conditional import to js_interop.
  • FEAT: update to web library.

8.1.4

  • FIX: fix an error when popping a nested route after flutter 3.22.0 #1973.

8.1.3

  • FIX: Fixed back gesture when nested navigator only has multi nested entries.
  • FIX: Can not swipe back on iOS when using nested navigation #1932.

8.1.2

  • FIX: Fixed back gesture when nested navigator only has one entry #1940

8.1.1

  • FIX: Can not swipe back on iOS when using nested navigation #1932.

8.1.0

  • FEAT: add deep-link transformer. Allows parsing the URI for deep links before the route matcher performs a match on the URI. Especially useful when you use intent-filter prefix on Android to only handle links from e.g com.example/FILTER.

    RouterConfig `<UrlState>` config({
    deepLinkTransformer : Deelkink.prefixStripper('FILTER'),
    )
    

    The resulting URI will be : com.example

8.0.2

  • FIX: only disable parent back gesture if the active child can pop.
  • FIX: AutoTabsRouterTabBarState was disposed with active Ticker #1910

8.0.1

  • FIX: back-gesture does not respect sub-routes.

8.0.0

  • FEAT: AutoTabsRouter will now use the declared routes if AutoTabsRouter.routes is not provided, if any of the tabs has required parameters it will throw an error.
  • BREAKING CHANGE: deep-links with no host e.g scheme://page/sub-page are no longer automatically handled, flutter's deep-link handler will treat [page] as host so we end up with [/sub-page] as a path which of course not going to match. if your deep-links are hostless you'll need to handle them manually inside deepLinkTransformer or deepLinkBuilder.

7.9.2

  • HOTFIX: fix an issue with deep-linking to tab-routes
  • CHORE: remove deprecated apis

7.9.1

  • FIX: incorrect top route information when deep-linking to an uninitialized tab route.

7.9.0

  • FIX: unable to get the label for back button(previous route title) and current route title on CupertinoNavigationBar and CupertinoSliverNavigationBar #1795.
  • FIX: CupertinoNavigationBar and CupertinoSliverNavigationBar unable to get route title and previous route title.
  • Fix: PopScope.onPopInvoked not called when canPop is set to true,
  • Refactor: rename router.pop to router.maybePop to avoid confusion
  • Refactor: rename router.popTop to router.maybePopTop to avoid confusion
  • Refactor: rename context.popRoute to context.maybePop

7.8.5

  • FEAT: add back mixin to AutoRouteAware
  • FIX: keep TabsRouter.homeIndex in sync with AutoTabsRouter.homeIndex

7.8.4

  • FIX: Build Runner Efficiency Warning #1737
  • FIX: ensure dynamic tab updates are handled in AutoTabsRouter.tabBar.
  • FEAT: AutoRoute.copyWith

7.8.3

  • FIX:

7.8.2

  • HOTFIX: update sdk constrains to flutter: >=3.13.0 and dart: >=3.0.0 <4.0.0

7.8.1

  • FIX: crash if pendingChildren are passed in as unmodifiable list.
  • DOCS: Fix typos and a broken links.
  • REFACTOR: remove usages of RouteInformation.location in favor of RouteInformation.uri

7.8.0

  • FEAT: add PlatformDeepLink.initial flag to tell whether we're coming from setInitialRoutePath or setNewRoutePath.
  • FEAT: add option to pass custom ignore_for_file rules to the generated file.
  • FEAT: support the new allowSnapshotting flag.

7.7.1

  • FIX: tab routes should be matched by key not name.

7.7.0

  • FEAT: Add basic support to dart records.
  • FIX: encoded path segments are not decoded in RouteMatch.pathParams
  • FIX: encoded browser path is checked against a decoded matched path when deciding whether to replace route #1637

7.6.0

  • FEAT: add 'scoped' argument to to StackRouter.removeUntil, if true the predicate will visit all StackRouters in hierarchy.
  • FEAT: add 'scoped' argument to to StackRouter.popUntil, if true the predicate will visit all StackRouters in hierarchy.

7.5.0

  • FIX: Uri percent-encoded characters encoded twice #1620.
  • FIX: delegate missing arguments in auto_route_guard redirect.
  • FEAT(auto_route): add AutoPageRouteBuilder.opaque argument.

7.4.0

  • FIX: StackRouter.replaceAll does not work with nested tab-routes.
  • FEAT: add optional flag to either update existing routes or not to StackRouter.replaceAll

7.3.2

  • FIX: Remove guard from ActiveGuardObserver when resolved with false.

7.3.1

  • FIX: DeferredWidget's default loader not working.
  • FEAT: DeferredWidget will now take AutoRouterDelegate.placeholder value if provided

7.2.3

  • FEAT: Add global guards reevaluate listenable
  • DOCS Add reevaluate listenable docs to README.md
  • FEAT: Add NavigationResolver.redirect method to auto-remove routes pushed by guards when resolving is complete
  • FEAT: Add AutoRoute.guarded constructor for cleaner single guard implementation

7.2.0

  • FEAT: add more flexible multi package support.
  • REFACTOR: resolve some flutter 3.10 deprecations.
  • DOCS(auto_route): fix typo.

7.1.0

  • FEAT: add support to process files in micro-packages.

7.0.0

Note: This release has breaking changes.

  • FIX: deepLinkBuilder is not called on newRoutePath.
  • BREAKING CHANGE: DefaultRouteParser.includePrefixMatches's value is now set to '!kIsWeb' instead of 'false'.
  • FEAT: add rebuildStackOnDeepLink flag to rebuild the whole stack on incoming deep-links

6.4.0

  • REFACTOR: deprecated initialDeepLink and initialRouts.
  • FEAT: Added DeepLinkBuilder to validate or override platform deep-links
  • FEAT: Added Route.data ext to get routeData of auto routes
  • DOCS: Updated docs

6.3.0

  • FEAT: Bring AutoRoute.initial back.

6.2.1

  • REFACTOR: make AutoRouterState and AutoTabsRouterState public.

6.2.0

  • Add public apis docs

ChangeLog

[6.1.0]

  • The missing hierarchy to a pushed child-route will now be auto_created if there are no required args
  • The root router can implement an AutoRouteGuard and guard all Stack-routes
  • Add restorationId builder to AutoRoute
  • Mark annotations with supported types [for static analysis]

[6.0.5]

  • Fix RouteMatch.fullPath is not joined properly
  • Add helper method to get route match PageRouteInfo().match(context)

[6.0.4]

  • Fix inherited path params are not working in v6
  • Add option to use cached_builds for more optimized generation

[6.0.3]

  • include merged pr's
  • [6.0.2]

  • Make AutoRoute.path call save

[6.0.1]

  • Fix bug with nested parent routes without path #1411

[6.0.0+1]

  • Use updated readme file

[6.0.0]

  • Fix secondAnimation value is always 0 in custom route transition

[6.0.0-rc-7]

  • Fix fullscreenDialog and maintainState flags are not passing to route data

[6.0.0-rc-6]

  • Fix topMostRouter is not always called on root-scope

[6.0.0-rc-5] Breaking

  • Fix but with new AutoTabsRouter.transition builder
  • rename AutoRouteBuilder to auto_route_generator in build.yaml file to follow naming convention [breaking]

[6.0.0-rc-4]

  • Fix android back button closes App
  • Add check for root routes must start with '/' or "*"

[6.0.0-rc-3] Breaking

  • Add transition builder to AutoTabsRouter and AutoTabsScaffold to only rebuild the body for animation and remove animation property from builder [breaking]
  • Add router.currentHierarchy() helper method for debugging and testing.
  • Add keepHistory flag to AutoRoute(), to remove route from stack on pushNext

[6.0.0-rc-2]

  • Fix CustomRoute.opaque not working

[6.0.0-rc-1]

  • Add path property to CustomRoute,CupertinoRoute and AdaptiveRoute
  • Add functionality to push path states to browser history and read it

[6.0.0-rc] Breaking

make sure you check the Migration guide

  • AutoRoute now takes a PageInfo object from the generated routes instead of Type
  • Introduce @RoutePage() annotation to annotate routable widgets
  • Routes are defined in the body of the router class instead of inside the annotation
  • Remove replace @MaterialAutoRouter,@CupertinoAutoRouter ...etc with @AutoRouterConfig annotation
  • Remove EmptyRouterPage & EmptyRouterScreen
  • "initial" flag is removed now, use "/" for initial routes or empty path "" for nested-initial routes.
  • Passing route guards is also changed now, instead of passing guards as types you now pass instances.
  • Add title builder for AutoRoute(title: (ctx,data){})
  • Docs are changed to reflect the new changes so make sure you re-read them.

[5.0.4]

  • Fix #1288

[5.0.3]

  • Fix redirect-route related issues
  • Fix didChangeTabRoute not called when using AutoTabsRouter.tabBar()

[5.0.2]

  • Change analyzer constrains to support up to version 6.0.0
  • Merge #1236
  • Merge add opaque property to AdaptiveRoute #1224
  • Merge readme.md file updates

[5.0.1]

  • Add ignorePagelessRoutes and ignoreChildRoutes property to AutoLeadingButton
  • Add builder property to AutoLeadingButton
  • Fix deferredLoading and AutoRouteWrapper are not working together

[5.0.0]

  • Add deferred loading support for web to enable code splitting for routes [By Garzas]
  • Move EmptyRouterScreen and EmptyRouterPage to a separate file to avoid import conflict when using deferred loading.
  • Fix a bug in Navigation History
  • Add License file to root package
  • Fix TabController dispose issue in AutoTabsRouter.tabBar
  • Add neglectWhen call back to ignore reporting location to engine
  • Remove universal_html dependency and implement own conditional html import

[4.2.1]

  • Fix AutoTabsRouter animation controller is disposed after super.dispose()
  • merge readme fixes

[4.2.0]

  • Add generate-time check for unresolvable path params
  • You can now access inherited path params using @pathParam annotation

[4.1.0]

  • Upgrade minimum Flutter SDK to 3.0.0
  • Upgrade minimum Dart SDK to 2.17.0
  • Fix PageView tabs implementation non-neighbor transition issue
  • Add scroll physics and dragStart behavior to booth tabBar nad pageView implementations

[4.0.1]

  • Fix incompatibility issues with flutter 3.0.0
  • fix reverseDurationInMilliseconds not being generated from router config

[4.0.0] (Breaking changes)

  • Refactor AutoRedirectGuard [Breaking Change]
  • Add AutoRouteAwareStateMixin to minimize boilerplate for AutoRouteAware states
  • Add NoShadowCupertinoTransitionsBuilder to remove unwanted shadow in nested cupertino routes
  • Add PageView support to AutoTabsRouter
  • Add TabBar support to AutoTabsRouter
  • Add custom builder support to AutoTabsRouter
  • Remove AutoTabsRouter.declarative implementation (replaced with builder) [Breaking Change]
  • AutoRouter.declarative routes now accepts a PendingRoutesHandler instead of context [Breaking Change]
  • Fix wrapped routes are rebuilt everytime the stack changes
  • Fix query params are not updated in Tab-Routes
  • Add router.activeGuardObserver to access active guards. e.g to implement loading indicator
  • Fix initial route is not showing when nested router is rebuilt
  • Replace AutoBackButton with AutoLeadingButton to support drawer and close icons

[3.2.4]

  • Fix path/query params are not updated in url when navigating to the same current path #854 #944

[3.2.3+1]

  • Remove forgotten print statement

[3.2.3]

  • Fix routes with empty path don't update url #960
  • Fix RouteInformationProvider.routerReportsNewRouteInformation required 'type' issue #958

[3.2.2]

-Add removeAllAndPush route strategy to auto_redirect_route

[3.2.1]

  • Merge some readme file typo-fixes
  • Add @optionalTypeArgs to AutoRoute annotations
  • Fix AdaptiveRoute issue with CustomRoute
  • Change analyzer constrains to include version 3.0.0
  • Add notify flag to removeWhere method inside of StackRouter

[3.2.0]

  • Merge fix conform new API in Flutter 2.6
  • Fix declarative routes update issue
  • Add Router tests

[3.1.3]

  • Fix navigateNamedTo does not update the stack #831
  • Refactor navigation history and set kept history records to 20 entries max

[3.1.2]

  • Fix Bad state: No element exception when setting initialRoutes #826
  • Fix conflict when param name is 'name' #824

[3.1.1]

  • Fix Regression bug (caused by immutable pendingRoutes list) #822

[3.1.0]

  • Prefer previous-current route index as new current index when updating tab routes #797
  • Improve native navigation history
  • Use browser history as navigation history in web
  • Fix path/query params not updating issue #809
  • Fix generic nullable types are generated as non-nullables #811
  • Override toString method inside of generated arg classes [FR] #820
  • Support redirect paths with path params [FR] #818
  • Fix replace/replaceNamed/replaceAll do not replace current url in browser #781

[3.0.4]

  • Fix IndexedStack widgets are not updated on tabs routes change.
  • Fix RangeError when updating routes in AutoTabsScaffold #788

[3.0.3]

  • Fix dynamic routes for AutoTabsScaffold don't work #783

[3.0.2]

  • Make AutoTabsScaffold builders rebuild on global routes hierarchy changes

[3.0.1]

  • Fix conflict with source_gen:combining_builder by using .gr.dart instead of .g.dart

[3.0.0]

  • Add option to use part builder .g.dart
  • Add option to pass const meta data from annotation to consumed route data.
  • Show better error message when router can not navigate to given route.
  • ancestor router can now push directly to nested router if it's already in stack.
  • Add navigateBack functionality
  • Add AutoRedirectRoute which reevaluates guarded routes that's already in stack

[2.4.2]

  • Add fullscreenDialog flag to pushWidget method
  • Add pushNativeRoute method

[2.4.1]

  • Fix pushing same route not rebuilding stack; effecting #717 #710
  • Fix dialogs/bottom sheets don't play nicely with auto_route when using nested routers
  • Add option to push an un-routable widgets to StackRouters
  • Add a comment containing the widget type reference to generated routes for easy source jumping

[2.4.0]

  • Fix url updates delay
  • Fix navigate does not update url
  • Add auto_route_information_provider.dart to fix infinite browser back button when using url redirects
  • optimize routes rebuild -> only rebuild if route data changes
  • Change routers are now not ( Watched ) by default to reduce rebuilds [ may Break]
  • Add optional homeIndex property to AutoTabsRouter to make sure we always pop from home tab
  • Change AutoBackButton to use StackRouterScope instead of RouterScope

[2.3.2]

  • Merge fix(generator): Bool opt type as num #688
  • Fix nested back gesture issue #686

[2.3.1]

  • Fix navigate to nested routes open last visited nested route #676
  • Add pop parent route support in AutoBackButton

[2.3.0]

  • Fix crash when passing non-string values as query params #606
  • Update analyzer version to 2.0.0
  • Update build_runner,build and source_gen versions
  • Merge #616 Export navigation failure
  • Merge #550 Enable AutoTabsScaffold to support custom appbar [Breaking]
  • Update README file

[2.2.1]

  • Fix crash when passing non-string values as query params #606
  • Update analyzer version to 2.0.0
  • Update build_runner,build and source_gen versions

[2.2.0] Breaking changes!

  • Remove helper methods pushToChild and replaceInChild from TabsRouter [Bad idea]. [Breaking]
  • Add navigate and navigateNamed methods to TabsRouter
  • Add navigateNamedTo method to context extension
  • Change context.navigateTo and context.navigateNamedTo will be fired by nearest RouterScope weather it's a StackRouter or a TabsRouter
  • Fix AutoRouteGuard is not fired when route is updating #517
  • Fix DidInitTabRoute method is fired when a route is pushed in AutoRouteAware widgets #518

[2.1.1] Breaking changes!

  • AutoRouteGuard's canNavigate method is now called onNavigation. [Breaking]
  • Add AutoRouteObserver to add support tab route observing.

[2.1.0] Breaking changes!

  • AutoRouteGuard no longer returns a future<bool> and passes in a resolver. [Breaking]
  • Remove onInitialRoutes from AutoRouterDelegate. [Breaking]
  • Rename RoutingControllerScope to RouterScope. [Breaking]
  • Expose provided navigatorObservers in RouterScope
  • Route name is now default page key with option to use path as key.
  • Add onNavigate callback function to AutoRouterDelegate
  • Add onNavigate all back to AutoRouter.declarative
  • Add declarative option to AutoTabsRouter

[2.0.1] Breaking changes!

  • OnPopRoute includes a results object now. [Breaking]
  • Remove usesTabsRouter property from AutoRoute as it's no longer needed.
  • Required queryParams to either be nullable or have a default value

[2.0.0] Breaking changes!

breaking changes
  • Remove usesTabsRouter property from AutoRoute as it's no longer needed.
  • onGenerateRoutes is now shortened to just routes and initial routes are no longer pass
  • Legacy generator is completely dropped now.
  • navigatorObservers is not a callback function that returns a list of observers
enhancements
  • Bring back the good old await for pop results feature.
  • The root AutoRouterDelegate can now be declarative.
  • Push, replace and navigate will now bubble up if they can't be handled by the router they're called from.
  • Enhance the navigate function to behave like navigating from the browser's bar.
  • Add new methods to navigate by path pushNamed, replaceNamed and navigateNamed.
  • Add AutoBackButton to handle nested routers popping with ease.
  • Add some helper/shortcut methods to context extension, pushRoute, replaceRoute, navigateTo and popRoute.
  • Add some helper methods to the RoutingController like popTop, topRoute and more.
  • Pages will rebuild when an ancestor router updates if you depend on it.
  • Add Auto RedirectRoute generation for Routes with none initial paths that's marked as initial.
  • Add AutoRouteObserver to add tabs observing to the native observer.
  • NavigatorObservers are now passed through a builder so nested navigators can inherit them.
  • Add HeroControllerScope to nested AutoRouters
  • Pomp up code_builder version to 4.0.0 and build_runner to 2.0.1
  • Fix #458, #456 #421 and #453
  • Minor fixes and enhancements

[1.0.2]

  • Pomp up versions of build, build_runner, dart_style and source_gen
  • Using pathParam annotation is not more flexible and has less constrains
  • Remove dart:io import to include (web) as a supported platform
  • other fixes

[1.0.1]

  • Fix Stack overflow in RootStackRouter popUntilRoot() #401
  • Fix path parameters are assigned an undefined var when alias is different than param name.

[1.0.0]

  • Migrate to null-safety
  • Add option to pass restoration id
  • Add option to specify the root navigator background color

[1.0.0-beta.10]

  • Fix generic parameters crash the generator
  • Add support for array type query params

[1.0.0-beta.9]

  • Fix navigatorKey state is lost on hot reload
  • Add stackRouterOfIndex getter function to AutoTabsRouter

[1.0.0-beta.8]

  • Add support for null-Safety to generated code.
  • Fix pop issues
  • Add popUntil, popUntilRoot and popUntilRouteWithName helper functions to StackRouter
  • Minor fixes Edit [BC] pushAndPopUntil uses the native predicate now.

[1.0.0-beta.7]

  • Fix onRoutePop not called in declarative router #310
  • Fix App reloads after pressing browser's back button #309
  • Fix TabsRouter not displaying current route when pressing the browser's back button
  • Add pop until method to StackRouter
  • Prefix parent routes are now included if includePrefixMatches is true
  • Add RouteMatcher tests
  • Minor improvements

[1.0.0-beta.6]

  • Fix reload issue when pressing the browser's back button #309
  • Fix onPopRoute is not called in declarative Router #310
  • Include empty paths as prefix-matched paths when deep-linking.
  • Remove unnecessary dependencies
  • Some minor improvements and code refactor

[1.0.0-beta.5]

  • Refactor some code
  • Update readme file

[1.0.0-beta.4]

  • Fix page can not be used for multiple routes
  • Add duplicate route-names check in generator.

[1.0.0-beta.3+1]

  • Fix badge alignment in readme file

[1.0.0-beta.3]

  • Fix crash on empty path deep-linking
  • Fix parent does not take priority when child can't pop
  • Change includePrefixMatches default value to false in DefaultRouteParser
  • Add some updates to Readme file

[1.0.0-beta.2]

  • Add lazyLoad option to AutoTabsRouter
  • Replace AutoRouterConfig with an implementation of StackRouter
  • Root delegate is now lazyLoaded

[1.0.0-beta.1] Breaking Changes!

  • Add TabsAutoRouter
  • Refactor some code

[1.0.0-beta] Breaking Changes!

  • Rebuild auto_route to work with Navigator 2.0

[0.6.9]

  • Fix generator error running flutter version 1.22
  • Fix bar-url not updated in flutter version 1.22

[0.6.7]

  • Fix blue screen issue when using guards on initial route #189
  • Fix relative import issues
  • Add option to not prefer relative imports
  • Fix some linter warnings
  • Fix issue #176

[0.6.6]

  • Fix hot reload issue #170
  • Fix Hero animations not working with the new ExtendedNavigator # 169
  • Add static builder to ExtendedNavigator to use with MaterialApp's builder

[0.6.5]

  • Downgrade path package to >= 1.6.4 to solve conflict with flutter_test
  • Clean up auto_route index file

[0.6.4]

  • Add usage of const constructors when possible
  • Fix material package is only imported if needed
  • Fix spelling mistakes in changeLog

[0.6.2] Breaking Change

  • Fix deep linking issue for nested routes
  • Change ExtendedNavigator to wrap the native navigator instead of extending it
  • Change generated class applies to most of effective dart rules including preferring relative imports
  • Change initial route placeholder color to white
  • Add extension to BuildContext to easily access the navigator
  • Remove NestedNavigator, ExtendedNavigator can be used directly as a nested navigator
  • Rename some properties and deprecate their older names
  • Remove ExtendedNavigator.ofRouter method
  • Minor fixes and enhancements

[0.6.1]

  • Fix pop until name issue by implementing PopUntilPath and RouteData.withPath
  • Fix opening deep links in new tabs pushes initial route only

[0.6.0+1]

  • Fix README file links

[0.6.0] Breaking Change

  • Change the way routes are declared from class fields to a static list
  • Add support for path & query parameters
  • Add support for path wildcards
  • Add support for nested routes
  • Add support for generic result types
  • Add a get ExtendedNavigator by name feature
  • Merge a fix for adaptive route web support issue
  • Change generating arguments holder for single parameter routes is not optional anymore
  • Minor fixes and enhancements

[0.5.0]

  • Add allRoutes getter to RouterBase
  • minor fixes

[0.4.6] Skip

[0.4.5] Breaking Change

  • Add AdaptiveAutoRouter and AdaptiveRoute for native platforms
  • Change using leading slashes is now options
  • Change wrappedRoute is now a function that takes in build context
  • Fix calling nested route returns null after popping parent route
  • Fix initial route ignore custom transitions
  • Add ability to name routes class

[0.4.4]

  • Change generating arguments holder for single parameter routes is not optional
  • Fix android soft back button always pops root navigator

[0.4.3] Breaking Changes

  • Add ability to pass initial route arguments to ExtendedNavigator
  • Change single route parameters will have argument holder classes too as requested
  • Fix ExtendedNavigator.ofRouter<T>() returns null in inspector mode

[0.4.2]

  • Fix Android soft back button always exists App

[0.4.1] Breaking Changes

  • Fix isInitialRoute not defined for RouteSettings in flutter 1.15.+

[0.4.0] Breaking Changes

  • Change using ExtendedNavigator instead of the native Navigator
  • Fix initial route does not go through guards
  • Change generated router class is no longer static
  • Change routes are generated in their own class now "Routers"
  • Add option to generate navigation helper methods extension
  • Update README file

[0.3.1]

  • Fix Compilation Fails in flutter 1.15.+
  • Fix third party imports src instead of library
  • Fix guardedRoutes is generated even if it's empty
  • Add support for custom unknown route screen

[0.3.0] Breaking Changes!

  • Add global route customization
  • Use MaterialAutoRouter, CupertinoAutoRouter or CustomAutoRouter instead of AutoRouter
  • Navigator key is now accessed by calling Router.navigator.key instead of Router.navigatorKey.
  • Add Route guards
  • Add optional returnType param in all AutoRoute types.
  • Remove generate Navigator Key optional.
  • Fix generate error when using dynamic vars in route widget constructors

[0.2.2]

  • Add option to generate a list with all route names
  • change generating navigator key is now optional
  • Fix prevent importing system library files
  • Change generated route path name are now Kabab cased (url-friendly)
  • Add ability to use custom path names in all route types
  • Update README file

[0.2.1]

  • add Route Wrapper
  • add initial flag as a property in all route types
  • change prefix const route names with class name.
  • add fullscreenDialog property to @CustomRoute()

[0.2.0+1]

  • format README file

[0.2.0]

Breaking Changes!

  • change to using a single config file instead of annotating the actual widget class due to performance issues.
  • add @MaterialRoute(), @CupertinoRoute() and @CustomRoute() annotations
  • remove @AutoRoute() annotation and add @AutoRouter()
  • handle required parameters.
  • add navigating with a global navigator key [without context].
  • support nested navigators.

[0.1.1]

  • code formatting.

[0.1.0]

  • initial release.

Installing

export PUB_HOSTED_URL=https://pub.mirror.p-hatan.com
flutter pub add 'auto_route:11.1.0'
pubspec.yaml
name: auto_route
description: AutoRoute is a declarative routing solution, where everything needed for navigation is automatically generated for you.
version: 11.1.0
homepage: https://github.com/Milad-Akarie/auto_route_library
screenshots:
  - description: 'Auto Route Logo'
    path: art/auto_route_logo.png
topics:
  - navigation
  - routing
  - auto-route
  - nested-navigation
  - deep-linking

environment:
  sdk: ">=3.0.0 <4.0.0"
  flutter: ">=3.16.0"

dependencies:
  flutter:
    sdk: flutter
  path: ^1.9.0
  web: ^1.0.0
  collection: ^1.18.0
  meta: ^1.16.0


dev_dependencies:
  build_runner:
  mockito: ^5.6.1
  auto_route_generator: ^10.4.0
  flutter_test:
    sdk: flutter
  flutter_lints: ^6.0.0

dependency_overrides:
  auto_route_generator:
    path: ../auto_route_generator


Version history

VersionPublishedArchiveSHA-256
0.1.0On demandDownloadef7260eb…8a06a6
0.1.1On demandDownloadfc85e26b…00c4c0
0.2.0On demandDownload5eb7326a…db2178
0.2.0+1On demandDownloadfbce659f…3b07fd
0.2.1On demandDownload8119aba4…6febe0
0.2.2On demandDownload1e51f24a…7cf4f7
0.3.0On demandDownload4f6007da…385097
0.3.1On demandDownload059f35f0…87e234
0.4.0On demandDownload0d183cb1…1979fd
0.4.1On demandDownloadbd08a56a…f0d446
0.4.2On demandDownload5c1743f2…cf8a29
0.4.3On demandDownload9130049d…753d7e
0.4.4On demandDownload66cdcf08…8fad77
0.4.5On demandDownload3b1e903b…cb3627
0.4.6On demandDownload0608457b…f9b7e3
0.5.0On demandDownloade6d2bba4…c16e61
0.6.0On demandDownloadf00b872a…2d9b8c
0.6.0+1On demandDownloadef770b63…229ebb
0.6.1On demandDownload5f1bd80f…7a9a6f
0.6.2On demandDownload800c0cb1…1f2063
0.6.4On demandDownloadaac49bfc…a5d0fb
0.6.5On demandDownload960bec35…4b5b6f
0.6.6On demandDownloadefe3b096…be74cf
0.6.7On demandDownload78bb6de4…372baf
0.6.9On demandDownloadf5ce2360…2aad04
1.0.0-betaOn demandDownload078611ea…a87896
1.0.0-beta.1On demandDownloada8ca0fe9…771bb5
1.0.0-beta.2On demandDownload652145b3…571596
1.0.0-beta.3On demandDownload5eab71be…2a8a28
1.0.0-beta.3+1On demandDownload39e38397…073f69
1.0.0-beta.4On demandDownload8d768fcf…d4cf9e
1.0.0-beta.5On demandDownloadbd994114…d132d7
1.0.0-beta.5+1On demandDownload844125bd…e859cb
1.0.0-beta.6On demandDownloadf82a3560…e341e8
1.0.0-beta.7On demandDownload01b9c10c…ac82fb
1.0.0-beta.8On demandDownload39e962b5…9cb17c
1.0.0-beta.9On demandDownloadc12c88be…590f36
1.0.0-beta.10On demandDownload4af82ed2…66f557
1.0.0On demandDownload4e826ecb…61eb1f
1.0.1On demandDownloadc34cb3a5…e7b7e1
1.0.2On demandDownload854cddd3…0694ae
2.0.0On demandDownload886106cd…1174c2
2.0.1On demandDownload2eed6927…4de045
2.0.2On demandDownloadfeb987dd…be9ed5
2.1.0On demandDownload76ab17e6…2aa28b
2.1.1On demandDownloadd9a60467…0d0f2a
2.2.0On demandDownloaddd07a8ec…c2ea74
2.3.0On demandDownload59813bf9…ebc1fd
2.3.1On demandDownload4bf12240…a9570d
2.3.2On demandDownload384a3e31…c01cbf
2.4.0On demandDownload768361b5…7271de
2.4.1On demandDownload6521e004…6451f7
2.4.2On demandDownload262ac068…3ed44d
3.0.0On demandDownload5a04f7ad…f6f189
3.0.1On demandDownload77405412…5267f1
3.0.2On demandDownload65b05431…13fb13
3.0.3On demandDownload8b1f0493…82d893
3.0.4On demandDownloadceec8289…608f12
3.1.0On demandDownload14877e02…35d13e
3.1.1On demandDownload60fd3756…ec09d5
3.1.2On demandDownload0d29d637…302c72
3.1.3On demandDownload01147545…1be63e
3.2.0On demandDownload300afadb…946243
3.2.1On demandDownload3cf2f338…aad524
3.2.2On demandDownload7ea01e61…e20ff7
3.2.3On demandDownload96555f91…3e1803
3.2.3+1On demandDownload6205c3cc…0dcafd
3.2.4On demandDownloadff22bcd3…d7891f
4.0.0On demandDownload67a010c6…1908fa
4.0.1On demandDownload57ae35dd…1e0acb
4.1.0On demandDownload66155c17…520a21
4.2.0On demandDownloaddb975a34…9a0308
4.2.1On demandDownload931f7c93…081a13
5.0.0On demandDownloadca42e93e…d716d6
5.0.1On demandDownload59eed373…13d249
5.0.2On demandDownloadd528758d…2613d9
5.0.3On demandDownloadef636fc4…8d011c
5.0.4On demandDownload12047bae…86f96d
6.0.0-rcOn demandDownload0aefa5a5…2463a4
6.0.0-rc-1On demandDownloadb769a8eb…cd90ec
6.0.0-rc-2On demandDownload4dc29309…b09631
6.0.0-rc-3On demandDownload5c79586f…f85d41
6.0.0-rc-4On demandDownloadc8ef6c89…fbd04c
6.0.0-rc-5On demandDownload85c34ca5…8d9875
6.0.0-rc-6On demandDownload1cfff5d3…1edc15
6.0.0-rc-7On demandDownload607dba9d…f1a779
6.0.0On demandDownload8b320fe6…e9b9b6
6.0.0+1On demandDownload7faca1e8…b86335
6.0.1On demandDownload70b2461c…d9c38b
6.0.2On demandDownload127005f7…11f052
6.0.3On demandDownload89a5fcc4…559998
6.0.4On demandDownload9c529031…e54251
6.0.5On demandDownloaddea16e1d…88a37c
6.1.0On demandDownloadc012d5c6…8dd134
6.2.0On demandDownload40405e4a…345486
6.2.1On demandDownloada29cbb3a…46486f
6.3.0On demandDownloadd161500c…58f8f2
6.4.0On demandDownload9a2579b1…f803c6
7.0.0On demandDownloadf0f8d7bd…f70a55
7.1.0On demandDownloadb7651565…14f82a
7.2.0On demandDownload56487504…b0c326
7.3.0On demandDownloadb9b9f8d1…dcdb1e
7.3.1On demandDownloadededc956…a34340
7.3.2On demandDownloadcf6cda30…a1ed9c
7.4.0On demandDownload02120972…27cdc6
7.5.0On demandDownload38f7b022…08a2df
7.6.0On demandDownloada2401341…6f86a8
7.7.0On demandDownload1d53010e…63ab16
7.7.1On demandDownload46037eb6…f3c29c
7.8.0On demandDownloadafa2e3a0…104671
7.8.1On demandDownload35e5c7f8…923f27
7.8.2On demandDownload60ad6fd7…8dd3b9
7.8.3On demandDownload72f21e8b…f0c271
7.8.4On demandDownload82f8df1d…3affa1
7.8.5On demandDownload2286341d…250897
7.9.0On demandDownload683bcee0…e3d72d
7.9.1On demandDownloadf103d0ea…220f2e
7.9.2On demandDownloadeb335545…908ff8
8.0.0On demandDownloadb8811ee8…c2f2c7
8.0.2On demandDownload6728027b…0a4955
8.0.3On demandDownloadf04022b2…9a13a3
8.1.0On demandDownload3cc59d11…a4f13f
8.1.1On demandDownload6d7ae781…6920fe
8.1.2On demandDownload1258bfcf…a8fbf0
8.1.3On demandDownload6cad3f40…e5080f
8.1.4On demandDownload8de4a280…657c7f
8.2.0On demandDownload878186aa…86d80d
8.3.0On demandDownloada9001a90…137704
9.0.0On demandDownloadab85e8e5…91f8ca
9.0.1On demandDownloadae11d059…6d0ff7
9.1.0On demandDownload0956ad9f…cdac90
9.2.0On demandDownloadbb673104…c1a7d6
9.2.1On demandDownloadd43d3119…0649e1
9.2.1+1On demandDownload90105037…b3c37c
9.2.2On demandDownloadb83e8ce4…76889b
9.3.0On demandDownload1688995b…3396bd
9.3.0+1On demandDownload1d1bd908…315ad7
10.0.0On demandDownloadfd5af38a…5468f2
10.0.1On demandDownload89bc5d17…cb9109
10.1.0On demandDownloadeae18fcd…8d1815
10.1.0+1On demandDownloadb8c036fa…4bbaf0
10.1.1On demandDownloadecb7491a…0d9e57
10.1.2On demandDownloadc820e918…e6be61
10.2.0On demandDownload14d4c91a…f744b5
10.2.1On demandDownload498502b5…781867
10.2.2On demandDownload4916e0fe…486ace
10.2.3On demandDownload9303e105…20c855
10.3.0On demandDownload6d3ccc11…6e8b43
11.0.0On demandDownloade2861f76…252d07
11.1.0Cached · Upstream SHA-256 matchedDownloade9acfeb3…dcd969
11.2.0Cached · Upstream SHA-256 matchedDownload538d8eb2…bfd229

Dependencies

collection "^1.18.0"

flutter { "sdk": "flutter" }

meta "^1.16.0"

path "^1.9.0"

web "^1.0.0"