Can I use optional parameter in path in Jetpack Compose Navigaiton?
Asked Answered
S

2

1

I have this navigation graph

fun NavGraphBuilder.manageAvailabilityGraph() {
    composable(
        "availability/{id}",
        arguments = listOf(
            navArgument("id") {
                type = NavType.StringType
                nullable = true
            },
        ),
    ) {
        ManageAvailabilityScreen()
    }
}

I thought I can use it for both

navHostController.navigate("availability")
navHostController.navigate("availability/123")

But first one does not work, I get

java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/availability } cannot be found in the navigation graph NavGraph(0x0) startDestination={Destination(0xcfbbf7da) route=home}

I fixed it by providing two different routes.

fun NavGraphBuilder.manageAvailabilityGraph() {
    composable(
        "availability",
    ) {
       ManageAvailabilityScreen()
    }

    composable(
        "availability/{id}",
        arguments = listOf(
            navArgument("id") {
                type = NavType.StringType
                nullable = true
            },
        ),
    ) {
        ManageAvailabilityScreen()
    }
}

However, I want to know is if it is possible to combine both and just have one route with name "availability", so I don't need to repeat "availability"? And eseentially, both use the same screen.

I tried something like this but does not work.

fun NavGraphBuilder.manageAvailabilityGraph() {
    composable(
        "availability",
    ) {

        ManageAvailabilityScreen()

        navigation(startDestination = "{id}", "{id}") {
            composable(
                "{id}",
                arguments = listOf(
                    navArgument("id") {
                        type = NavType.StringType
                    },
                ),
            ) {
                ManageAvailabilityScreen()
            }
        }
    }
}

Simonette answered 23/8, 2022 at 3:50 Comment(0)
D
2

You can mark id as the optional parameter in the route. Refer Documentation

fun NavGraphBuilder.manageAvailabilityGraph() {
    composable(
        "availability?id={id}",
        arguments = listOf(
            navArgument("id") {
                type = NavType.StringType
                nullable = true
            },
        ),
    ) {
        ManageAvailabilityScreen()
    }
}

While navigating you can use,

navHostController.navigate("availability")
navHostController.navigate("availability?id=123")
Dagon answered 23/8, 2022 at 4:16 Comment(0)
K
0

You can use "Optional argument" as following

Screen.Kt

const val PASTED_TEXT_ARG_KEY = "pasted_screen_arg_key"

sealed class Screen(val route: String) {
    data object Translate : Screen(route = "translate_screen/{$PASTED_TEXT_ARG_KEY}") {
        fun passPastedText(pastedText: String? = null): String {
            return "translate_screen/$pastedText"
        }
    }
}

NavGraph.Kt

@Composable
fun SetupNavGraph(
    navController: NavHostController,
    startDestination: String
) {
    NavHost(navController, startDestination) {
        composable(
            route = Screen.Translate.route,
            arguments = listOf(
                navArgument(PASTED_TEXT_ARG_KEY) {
                    nullable = true
                    type = NavType.StringType
                }
            )
        ) {
            it.arguments?.getString(PASTED_TEXT_ARG_KEY).let { pastedText ->
                TranslateScreen(
                    navController = navController,
                    pastedText = pastedText
                )
            }
        }
    }
}

example of usage

navController.navigate(Screen.Translate.passPastedText()) // Or use following
navController.navigate(Screen.Translate.passPastedText("with_some_value"))
Kt answered 31/12, 2023 at 16:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.