Complete beginner here, so forgive me if I'm missing something obvious.
I am trying to navigate with jetpack compose Modal Navigation Drawer, using a viewmodel to pull entries out of a table.
I have successfully set up a load screen to choose from the list of entries in the database and navigate to the next page; however, I can't work out how to save this ID for travelling between pages with the navigation drawer.
Main App
@Composable
fun MyApp(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
) {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
ModalNavigationDrawer(
drawerState = drawerState,
modifier = Modifier,
drawerContent = {
ModalDrawerSheet(
modifier = Modifier.fillMaxWidth(0.5f),
) {
Text(
stringResource(R.string.meat_space),
textAlign = TextAlign.Center
)
Divider()
NavDrawerItem(
label = FrontPageDestination.titleRes,
onClick = {
if (currentRoute != FrontPageDestination.route) {
navController.navigate(FrontPageDestination.route) {
launchSingleTop = true
}
}
coroutineScope.launch { drawerState.close() }
}
)
NavDrawerItem(
label = SecondPageDestination.titleRes,
onClick = {
navController.navigate(SecondPageDestination.route) {
coroutineScope.launch { drawerState.close() }
}
}
)
//more navdrawer items to be added here
}
}
) {
Scaffold(
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
CenterAlignedTopAppBar(
title = {
if (currentRoute != FrontPageDestination.route) {
Text(currentRoute.replaceFirstChar { it.uppercase() })
}
},
navigationIcon = {
if (currentRoute != FrontDestination.route) {
IconButton(onClick = {
coroutineScope.launch { drawerState.open() }
}) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = stringResource(R.string.open_navigation_drawer)
)
}
}
},
scrollBehavior = scrollBehavior,
modifier = Modifier,
)
},
) {
Surface(
modifier = Modifier
.fillMaxSize()
.padding(top = it.calculateTopPadding())
) {
MyAppNavHost(navController = navController)
}
}
}
}
with more pages to be added in drawer items that can be called with the ID
Then in the NavHost:
@Composable
fun MyAppNavHost(
navController: NavHostController,
modifier: Modifier = Modifier
) {
NavHost(
navController = navController,
startDestination = FrontPageDestination.route,
modifier = modifier
) {
composable(FrontPageDestination.route) {
FrontScreen(
navigateToSecondPage = { navController.navigate("${SecondPageDestination.route}/${it}") }
)
}
composable(
route = SecondPageDestination.routeWithArgs,
arguments = listOf(navArgument(SecondPageDestination.entryIdArg) {
type = NavType.IntType
})
)
{
SecondPageScreen()
}
//composable...
}
}
And finally, in the Front Page screen I have the load button which works successfully:
LoadIdDialog(
onDismissRequest = { },
idList = idList,
onIdClick = { onIdClick(it.id) },
modifier = Modifier
)
}
}
}
}
The entire page of code is quite long and links into the viewmodel, but I can post if needed
How do I navigate between Navigation Drawer pages while retaining the database id?
I tried
NavDrawerItem(
label = SecondPageDestination.titleRes,
onClick = {
navController.navigate(SecondPageDestination.routeWithArgs) {
coroutineScope.launch { drawerState.close() }
}
}
)
and also
navController.navigate("${SecondPageDestination.route}/{$entryIdArg}")
But these both give the error
java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/secondpage/{entryId} } cannot be found in the navigation graph
I think if I could extract the entryId as its string value to put it back into the drawer navigation it might work? But not sure how to do that.
It seems like the only way to do this that I can work out is to have the nav drawer composed with every separate page and each of those pages have nav functions to every other page on the list.
A bit clunky, and means recomposition of the nav drawer with every page but not sure how else to do it.