I am coding an app with Flutter. I am using go_router: ^4.2.7 to navigate between pages. It's a learning app. In the section "my_course_materials_page.dart" there is a widget that opens a page passing a String that contains a URL for opening a pdf into a Container() (package is: syncfusion_flutter_pdfviewer: ^20.2.48-beta). I can open the pdf in the widget, but when I try to navigate to the page that should show the material (my_course_material_page.dart) the app crashes with the following error:
Exception has occurred.
_AssertionError ('package:go_router/src/configuration.dart': Failed assertion: line 74 pos 16: 'paramNames.contains(key)': unknown param "materialURL" for /login/myCourses/myCourseMaterials/myCourseMaterial)
Here are the various files:
- The button that opens the page is into "material_element_card.dart:
ElevatedButton(
onPressed: () {
context.goNamed(AppRoute.myCourseMaterial.name,
params: {
'materialURL': materialURL,
});
},
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(60),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
),
child: const Text('View PDF'),
),
- The page that will show the pdf: "my_course_material_page.dart"
import 'package:flutter/material.dart';
...
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
class MyCourseMaterialPage extends StatelessWidget {
MyCourseMaterialPage({required this.materialURL, super.key});
final String materialURL;
final PdfViewerController _pdfViewerController = PdfViewerController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(slivers: [
const MyCourseSliverAppBar(
courseId: 001,
headerTitle: 'Material',
courseTitle: 'MO20222023',
courseLocation: '',
courseStartDate: '2022-09-01',
courseEndDate: '2023-06-01',
courseHeaderImageBackground:
'assets/images/course_placeholder.png',
),
SliverToBoxAdapter(
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: const Color.fromARGB(250, 30, 41, 62),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Expanded(
child: IconButton(
onPressed: () {
_pdfViewerController.zoomLevel++;
},
icon: const Icon(Icons.zoom_in)),
),
Expanded(
child: IconButton(
onPressed: () {
_pdfViewerController.zoomLevel--;
},
icon: const Icon(Icons.zoom_out)),
),
Expanded(
child: IconButton(
onPressed: () {
_pdfViewerController.previousPage();
},
icon: const Icon(Icons.navigate_before)),
),
Expanded(
child: IconButton(
onPressed: () {
_pdfViewerController.nextPage();
},
icon: const Icon(Icons.navigate_next)),
),
],
),
),
kSpacerSmall,
SizedBox(
width: double.infinity,
height: 420,
child: SfPdfViewer.network(
materialURL,
pageLayoutMode: PdfPageLayoutMode.single,
controller: _pdfViewerController,
),
),
],
),
),
]),
);
}
}
- the file that holds all the go_router logic: "app_router.dart"
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
... (all pages/screens import)
enum AppRoute {
start,
login,
register,
coursesCatalog,
coursesCatalogCategory,
courseDetails,
news,
singleNews,
school,
contact,
userSection,
myDashboard,
myProfile,
myCourses,
myCourse,
myCourseDashboard,
myCourseCalendar,
myCourseProgram,
myCourseMaterials,
myCourseMaterial,
myCourseHomeworks,
myCourseHomework,
myCourseNotifications,
myCourseNotification,
myCourseVimeo,
myCourseZoom,
mySettings,
myNotifications,
myNotification,
myHelp,
}
final goRouter = GoRouter(
initialLocation: '/',
debugLogDiagnostics: true,
routes: [
GoRoute(
path: '/',
name: AppRoute.start.name,
builder: (context, state) => const StartPage(),
routes: [
// COURSES CATALOG SECTION
GoRoute(
path: 'coursesCatalog',
name: AppRoute.coursesCatalog.name,
pageBuilder: (context, state) => CustomTransitionPage<void>(
key: state.pageKey,
child: const CoursesCatalog(),
transitionsBuilder:
(context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
),
...
// LOGIN SECTION
GoRoute(
path: 'login',
name: AppRoute.login.name,
pageBuilder: (context, state) => CustomTransitionPage<void>(
key: state.pageKey,
child: const LoginPage(),
transitionsBuilder:
(context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
),
routes: [
// USER SECTION
GoRoute(
path: 'myDashboard',
name: AppRoute.myDashboard.name,
pageBuilder: (context, state) => CustomTransitionPage<void>(
key: state.pageKey,
child: const MyDashboardPage(),
transitionsBuilder:
(context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
),
routes: [
// MY PROFILE SECTION
],
),
GoRoute(
path: 'myProfile',
name: AppRoute.myProfile.name,
// builder: (context, state) => const MyProfilePage(),
// path: '/fade',
pageBuilder: (context, state) => CustomTransitionPage<void>(
key: state.pageKey,
child: const MyProfilePage(),
transitionsBuilder:
(context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
),
),
// MY COURSES SECTION
GoRoute(
path: 'myCourses',
name: AppRoute.myCourses.name,
pageBuilder: (context, state) => CustomTransitionPage<void>(
key: state.pageKey,
child: const MyCoursesPage(),
transitionsBuilder:
(context, animation, secondaryAnimation, child) =>
FadeTransition(opacity: animation, child: child),
),
routes: [
GoRoute(
path: 'myCourse',
name: AppRoute.myCourse.name,
pageBuilder: (context, state) => MaterialPage(
key: state.pageKey,
fullscreenDialog: true,
child: const MyCourseGeneralInfoPage(),
),
),
GoRoute(
path: 'myCourseCalendar',
name: AppRoute.myCourseCalendar.name,
pageBuilder: (context, state) => MaterialPage(
key: state.pageKey,
fullscreenDialog: true,
child: const MyCourseCalendarPage(),
),
),
GoRoute(
path: 'myCourseMaterials',
name: AppRoute.myCourseMaterials.name,
pageBuilder: (context, state) => MaterialPage(
key: state.pageKey,
fullscreenDialog: false,
child: const MyCourseMaterialsPage(),
),
routes: [
GoRoute(
path: 'myCourseMaterial',
name: AppRoute.myCourseMaterial.name,
pageBuilder: (context, state) {
final materialSingleURL = state.params['materialURL']!;
return MaterialPage(
// arguments: materialURL,
key: state.pageKey,
fullscreenDialog: false,
child: MyCourseMaterialPage(
materialURL: materialSingleURL,
),
);
},
),
],
),
...
),
],
),
],
...
),
],
errorBuilder: (context, state) => const NotFoundScreen(),
);
The specific route that is called by the ElevatedButton (1.), is:
GoRoute(
path: 'myCourseMaterial',
name: AppRoute.myCourseMaterial.name,
pageBuilder: (context, state) {
final materialSingleURL = state.params['materialURL']!;
return MaterialPage(
key: state.pageKey,
fullscreenDialog: false,
child: MyCourseMaterialPage(
materialURL: materialSingleURL,
),
);
},
),
All other routes work perfectly and the app opens every page.
This exception is thrown only when I tap on the EB that has the param materialURL
that should be passed to the my_course_material_page.dart
, in order to show the pdf.
Any hint/idea?