Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass an argument to a nested navigation graph in Jetpack Compose

From the docs, I see you can nest navigation graphs like so:

NavHost(navController, startDestination = "home") {
    ...
    // Navigating to the graph via its route ('login') automatically
    // navigates to the graph's start destination - 'username'
    // therefore encapsulating the graph's internal routing logic
    navigation(startDestination = "username", route = "login") {
        composable("username") { ... }
        composable("password") { ... }
        composable("registration") { ... }
    }
    ...
}

I am wondering, how would one pass an argument in the route, and make that available to all composables inside the nav graph?

Here's my current nav graph:

navigation(
    // I'd like to grab this parameter
    route = "dashboard?classId={classId}",
    startDestination = Route.ScreenOne.route) {
    composable(Route.ScreenOne.route) {
        // And then pass the parameter here, or to any composable below
        ScreenOne(classId)
    }
    composable(Route.ScreenTwo.route) {
        ScreenTwo()
    }
    composable(Route.ScreenThree.route) {
        ScreenThree()
    }
}

I am basically trying to avoid setting the classId navigation argument individually on each composable route. I didn't see a way to pass a list of arguments to navigation() like you can in a composable().

It might be that what I am describing isn't possible, but looking forward to anyone's thoughts!

like image 944
Eric Avatar asked Dec 18 '25 14:12

Eric


2 Answers

UPDATE: 6th April 2023 - Previously my answer was broken. I've now updated this to get the back stack entry from the nav controller. This solution now works.


Yes, this is perfectly possible - took me a while as the documentation is lacking (they explain Navigation arguments, and Nested Graphs, but not both!).

You will need access to your navController to do this.

You call getBackStackEntry on the navController to get the top most entry. It will need wrapping inside a remember(entry) { } block as you are calling it inside a Composable.

private fun NavGraphBuilder.yourNestedGraph(navController: NavHostController) {
    navigation(
        route = "dashboard?classId={classId}",
        startDestination = "yourStartDestination",
        arguments = listOf(navArgument("classId") { type = NavType.StringType })
    ) {
        composable(route = "yourStartDestination") { entry ->
            val parentEntry = remember(entry) { navController.getBackStackEntry("dashboard?classId={classId}") }
            val classId = parentEntry.arguments?.getString("classId")
            YourScreenComposable(classId)
        }
        composable(route = "someOtherNestedRoute") { entry ->
            val parentEntry = remember(entry) { navController.getBackStackEntry("dashboard?classId={classId}") }
            val classId = parentEntry.arguments?.getString("classId")
            AnotherScreen(classId)
        }
        composable(route = "andAnotherNestedRoute") { entry ->
            val parentEntry = remember(entry) { navController.getBackStackEntry("dashboard?classId={classId}") }
            val classId = parentEntry.arguments?.getString("classId")
            AndAnotherScreen(classId)
        }
    }
}

** Important Note ** - You may need to type the navigation function again and import it - similar to the issue mentioned in the question, I also couldn't see an arguments parameter at first in my existing navigation functions, but when I typed out navigation again inside my NavGraphBuilder I saw the other option which did have the arguments parameter.

like image 188
Vin Norman Avatar answered Dec 21 '25 05:12

Vin Norman


You can access the graph arguments from child composables:

navController.getBackStackEntry("dashboard?classId={classId}").arguments?.getString("classId")
like image 41
wrsx Avatar answered Dec 21 '25 05:12

wrsx