π§© GoRouter Modular π
Dependency injection and route management
Perfect for micro-frontends and event-driven communication
GoRouter Modular simplifies Flutter development by implementing a modular architecture with GoRouter for route management π§© and supports per-module dependency injection with auto-dispose π.
Perfect for micro frontends and large-scale applications! π
Complete Documentation
Contents
- Key Features
- Why GoRouter Modular?
- Quick Start
- Dependency injection
- Event System
- Navigation Examples
- Useful Links
- Contributing
- License
β¨ Key Features
- π§© Modular Architecture - Independent, reusable modules
- π Dependency Injection - Built-in DI with auto-dispose
- π£οΈ GoRouter Integration - Type-safe and declarative navigation
- π Event System - Event-driven communication between modules
- π Performance - Lazy loading and efficient memory management
- π‘οΈ Type Safety - Fully type-safe with compile-time error detection
π§ Why GoRouter Modular?
- Real scalability: independent modules and lazy loading keep your app lightweight.
- Clear organization: routes and injections live within their features, improving maintainability.
- Dependency isolation: each module manages its own binds with automatic disposal.
- Decoupled communication: built-in event system across modules.
- Developer productivity: simple API on top of GoRouter without sacrificing flexibility.
β‘ Quick Start
π¦ Install
flutter pub add go_router_modular
dependencies:
flutter:
sdk: flutter
go_router_modular: ^any
π§© Create core files
lib/src/app_widget.dart
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:go_router_modular/go_router_modular.dart';
class AppWidget extends StatelessWidget {
const AppWidget({super.key});
@override
Widget build(BuildContext context) {
return ModularApp.router(
scrollBehavior: const MaterialScrollBehavior().copyWith(
dragDevices: {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
},
),
title: 'Modular GoRoute Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
);
}
}
lib/src/app_module.dart
import 'package:go_router_modular/go_router_modular.dart';
class AppModule extends Module {
@override
FutureOr<List<Bind<Object>>> binds() => [
// Bind.singleton<HomeController>((i) => HomeController()),
];
@override
List<ModularRoute> get routes => [
// ModuleRoute('/', child: (context, state) => HomeModule()),
];
}
π Configure App
lib/main.dart
import 'package:flutter/material.dart';
import 'package:go_router_modular/go_router_modular.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Modular.configure(
appModule: AppModule(),
initialRoute: "/",
debugLogDiagnostics: true,
debugLogDiagnosticsGoRouter: true,
);
runApp(AppWidget());
}
π§© Module Example
class HomeModule extends Module {
@override
FutureOr<List<Bind<Object>>> binds() => [
Bind.singleton<HomeController>((i) => HomeController()),
];
@override
List<ModularRoute> get routes => [
ChildRoute('/', child: (context, state) => HomePage()),
ChildRoute('/profile', child: (context, state) => ProfilePage()),
];
}
π Dependency injection
Example of binds in the feature package:
// features/cart/lib/cart_module.dart
class CartModule extends Module {
@override
FutureOr<List<Bind<Object>>> binds() => [
Bind.singleton<CartController>((i) => CartController()),
Bind.factory<CartService>((i) => CartService()),
];
@override
List<ModularRoute> get routes => [
ChildRoute('/', child: (context, state) => CartPage()),
];
}
How to use your injected dependencies
You can retrieve your dependencies in two main ways:
1. Using Modular.get<T>()
anywhere:
final cartController = Modular.get<CartController>();
2. Using context.read<T>()
inside a widget:
class CartPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final cartController = context.read<CartController>();
// Use cartController as needed
return ...;
}
}
- Use
Modular.get<T>()
for global access (not recommended inside widgets). - Use
context.read<T>()
for widget-specific access (recommended for UI).
π Event System
class NotificationModule extends EventModule {
@override
void listen() {
on<ShowNotificationEvent>((event, context) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(event.message)),
);
});
}
}
// Fire event
ModularEvent.fire(ShowNotificationEvent('Hello!'));
π£οΈ Navigation Examples
Basic Navigation
// Navigate to a route
context.go('/profile');
// Push a new route
context.push('/settings');
// Go back
context.pop();
Navigation with Parameters
// Navigate with path parameters
context.go('/user/123');
// Navigate with query parameters
context.go('/search?q=flutter&category=all');
// Navigate with extra data
context.go('/product', extra: {'id': 456, 'name': 'Flutter Book'});
Async Navigation
ElevatedButton(
onPressed: () async {
// Show loading
ModularLoader.show();
// Perform async operation
await Future.delayed(Duration(seconds: 2));
// Navigate
await context.goAsync('/heavy-page');
// Hide loading
ModularLoader.hide();
},
child: Text('Navigate with Loading'),
),
π Useful Links
- π Complete Documentation
- π¦ Pub.dev
- π Issues
- β GitHub
π€ Contributing
Contributions are very welcome! Open an issue to discuss major changes and submit a PR with clear descriptions of the edits.
- Follow the project conventions and keep docs updated.
- Add small usage examples when introducing new features.
π License
This project is distributed under the MIT license. See LICENSE
for details.
π Happy Coding with GoRouter Modular! π
Transform your Flutter app into a scalable, modular masterpiece β¨
Made with contrib.rocks