modular_router 2.0.0 copy "modular_router: ^2.0.0" to clipboard
modular_router: ^2.0.0 copied to clipboard

A flutter package to manage routes

Modular Router 🚀 #

Pub Version License Flutter

A powerful, modular, and type-safe routing solution for Flutter applications. Manage complex navigation structures, dependency injection, and authorization with ease.


✨ Features #

  • 🏆 Modular Architecture: Organize your app into logical features (modules).
  • 🌲 Nested Routing: Create hierarchical path structures effortlessly.
  • 💉 Built-in Dependency Injection: Powered by auto_injector and dynamic_constructor.
  • 🛡️ Integrated Authorization: Control access at both module and route levels.
  • 📍 Type-Safe Navigation: Navigate using types instead of hardcoded strings.
  • 📱 Platform-Native Transitions: Automatic Material/Cupertino transitions.
  • 🎨 Custom Transitions: Full control over page transitions when needed.
  • 🔧 Stateful Integration: Seamlessly binds Controllers to StatefulWidgetBinder views.

🚀 Getting Started #

1. Installation #

Add modular_router to your pubspec.yaml:

dependencies:
  modular_router: ^2.0.0

2. Define your Modules and Routes #

Create a module by extending Module and define its routes. Views should extend StatefulWidgetBinder and Controllers should implement DisposableController.

class UserModule extends Module {
  UserModule() : super(path: '/user');

  @override
  List<ModuleRoute> get routes => [
    ModuleRoute<ProfilePage>(
      path: '/profile',
      viewBuilder: ProfilePage.new,
      controllerBuilder: ProfileController.new,
    ),
    ModuleRoute<SettingsPage>(
      path: '/settings',
      viewBuilder: SettingsPage.new,
      controllerBuilder: SettingsController.new,
    ),
  ];
}

3. Initialize the Router #

Create your router and pass its onGenerateRoute to your MaterialApp.

final router = ModularRouter(
  modules: [
    UserModule(),
    // ... other modules
  ],
);

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      onGenerateRoute: router.onGenerateRoute,
      initialRoute: '/user/profile',
    );
  }
}

💉 Dependency Injection #

ModularRouter uses auto_injector to handle dependencies. You can register factories, lazy singletons, or singletons during initialization:

final router = ModularRouter(
  modules: [ ... ],
  factories: [
    Injector<AuthService>(AuthService.new),
  ],
  singletons: [
    Injector<ApiClient>(ApiClient.new),
  ],
);

Or by extending ModularRouter:

class MyRouter extends ModularRouter {
  MyRouter({required super.modules}) : super(
    factories: [ ... ],
  );
}

Dependencies are automatically injected into your viewBuilder and controllerBuilder based on their constructor parameters!

Required Base Classes

For DI and binding to work, follow these base class requirements:

  • Views: Must extend StatefulWidgetBinder.
  • Controllers: Must implement DisposableController (or use ListenableController for reactivity).
class MyController extends ListenableController {
  @override
  void dispose() {
    super.dispose();
  }
}

class MyPage extends StatefulWidgetBinder {
  const MyPage({required super.controller, super.key});

  @override
  State<MyPage> createState() => _MyPageState();
}

📍 Type-Safe Navigation #

Forget about hardcoded path strings. Use the provided extensions on NavigatorState:

// Push to a specific view type
Navigator.of(context).pushTo<ProfilePage>();

// Push and replace
Navigator.of(context).pushToReplacement<SettingsPage>();

// Push and remove until
Navigator.of(context).pushToAndRemoveUntil<DashboardPage, LoginPage>();

// Pop all and push
Navigator.of(context).popAllAndPushTo<HomePage>();

📦 Passing Arguments #

ModularRouter makes it incredibly easy to pass data directly into your controller or view constructors. The system handles DI automatically, but you can also pass custom arguments via the Navigator:

1. Positional Arguments #

Just pass your arguments as a List:

// Controller constructor: SettingsController(this.username, this.userId)
Navigator.of(context).pushTo<SettingsPage>(
  arguments: ['tercyo', 123],
);

2. Named Arguments #

Pass your arguments as a Map:

// Controller constructor: ProfileController({required String bio})
Navigator.of(context).pushTo<ProfilePage>(
  arguments: {'bio': 'Always building 🚀'},
);

3. Mixed Arguments #

Pass a List with a Map as the last element:

// Controller constructor: UserDetailController(this.userId, {required String source})
Navigator.of(context).pushTo<UserDetailPage>(
  arguments: [123, {'source': 'profile_view'}],
);

🛡️ Authorization #

You can easily protect routes or entire modules:

class AdminModule extends Module {
  AdminModule() : super(
    path: '/admin',
    allowAnonymous: false, // Requires authorization
  );

  @override
  List<ModuleRoute> get routes => [
    ModuleRoute<Dashboard>(
      path: '/',
      viewBuilder: AdminDashboard.new,
    ),
    ModuleRoute<PublicInfo>(
      path: '/info',
      viewBuilder: PublicInfoPage.new,
      allowAnonymous: true, // Override module setting
    ),
  ];
}

Initialize your router with the current auth state:

final router = MainRouter(
  modules: [...],
  enableAuthorize: true,
  authorized: userIsLoggedIn,
  unauthorizedRedirectRoute: '/login',
);

🛠️ Advanced Usage #

Custom Page Transitions #

ModuleRoute<PremiumPage>(
  path: '/premium',
  viewBuilder: PremiumPage.new,
  customPageTransition: <T>({settings, required view}) {
    return PageRouteBuilder<T>(
      settings: settings,
      pageBuilder: (context, animation, secondaryAnimation) => view,
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        return FadeTransition(opacity: animation, child: child);
      },
    );
  },
);

🎨 Example #

Check out the example project for a complete demonstration, including:

  • Module and Route definitions
  • Dependency Injection with a global Config object
  • Counter state management using ListenableController
  • Type-safe Navigation using NavigatorStateExtension

📄 License #

This project is licensed under the MIT License - see the LICENSE file for details.

2
likes
140
points
95
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A flutter package to manage routes

Repository (GitHub)
View/report issues

License

BSD-2-Clause (license)

Dependencies

auto_injector, collection, dynamic_constructor, flutter, stateful_widget_binder

More

Packages that depend on modular_router