passing optional arguments in compose navigation start destination?

297 Views Asked by At

I've been trying to send a destination with optional parameter to navigation start destination for 2 days, but I found out that this is not possible. The start destination of the navigation had to match the character-by-character route, so it had to be exactly the same, so I've been encountering this error for 2 days.

java.lang.IllegalArgumentException: navigation destination verification_phone_code_screen?isRedirectFromLoginOrSplash=true is not a direct child of this NavGraph

What I did:

I wrote a function that determines the screen to go to in MainActivity, it specifies where to go according to these conditions.

private fun navigateIfNeeded(response: NavigateState, isTokenExist:Boolean): String {


        return when {
            !isTokenExist -> RegisterScreen.SignUpStartRegisterScreen.route
            response.hasValidation == 0 -> "${RegisterScreen.SignUpVerificationPhoneCodeScreen.route}?$EMAIL={$EMAIL}&$PHONE={$PHONE}&$IS_REDIRECT_FROM_LOGIN_OR_SPLASH={$IS_REDIRECT_FROM_LOGIN_OR_SPLASH}" 
            response.hasValidation == 1 -> {
                when (response.eatingHabit) {
                    0 -> {
                        if (response.weight == 0 || response.goalWeight == 0) {
                            return RegisterScreen.SignUpDailyCalorieGoalScreen.route
                        } else{
                            return DASHBOARD_ROUTE
                        }
                    }
                    else -> RegisterScreen.SignUpPaymentScreen.route
                }
            }
            else -> DASHBOARD_ROUTE
        }
    }

response.hasValidation == 0 -> "${RegisterScreen.SignUpVerificationPhoneCodeScreen.route}?$EMAIL={$EMAIL}&$PHONE={$PHONE}&$IS_REDIRECT_FROM_LOGIN_OR_SPLASH={$IS_REDIRECT_FROM_LOGIN_OR_SPLASH}"

When the following condition works, it gives an error here, of course, since I gave the full path, it goes smoothly, but what I want to do here is to pass the true booelan value to the IS_REDIRECT_FROM_LOGIN_OR_SPLASH parameter, but this is not possible as far as I understand

I'm sending the start destination to my Root NavGraph like this MainActivity setContent setContent {

            AppTheme {
                navHostController = rememberNavController()
                Surface(
                    modifier = Modifier
                        .fillMaxSize()
                ) {
                    RootNavGraph(navHostController = navHostController, startDestination)
                }
            }
        }

and I get it in Root NavGraph and set it like this

If the incoming startDestination value is dashboard route, I say go to DASHBOARD_ ROUTE, if it is not dashboard route, I go to REGISTER_LOGIN_ROUTE. There is no problem here

@Composable
fun RootNavGraph(
    navHostController: NavHostController,
    startDestination: String,
) {

    val sharedViewModel: SharedViewModel = viewModel()

    val startRoute =
        if (startDestination != DASHBOARD_ROUTE) REGISTER_LOGIN_ROUTE else DASHBOARD_ROUTE

    NavHost(
        navController = navHostController,
        startDestination = startRoute,
        route = ROOT_ROUTE
    )
    {
        registerLoginNavGraph(navHostController, sharedViewModel, startDestination)
        dashBoardNavGraph(navHostController, sharedViewModel)
    }
}

where i want to go next is the place i ask in this problem so SignUpVerificationPhoneCodeScreen registerLoginNavGraph is also

hear is my registerLoginNavGraph

fun NavGraphBuilder.registerLoginNavGraph(
    navHostController: NavHostController,
    sharedViewModel: SharedViewModel,
    startDestination: String,
) {

    val _startDestination =
        if (startDestination == "")
            RegisterScreen.SignUpStartRegisterScreen.route
        else
            startDestination


    navigation(
        startDestination = _startDestination,
        route = REGISTER_LOGIN_ROUTE
    ) {
       .
       .
       .
     composable(
            route = "${RegisterScreen.SignUpVerificationPhoneCodeScreen.route}?$EMAIL={$EMAIL}&$PHONE={$PHONE}&$IS_REDIRECT_FROM_LOGIN_OR_SPLASH={$IS_REDIRECT_FROM_LOGIN_OR_SPLASH}",
            arguments = listOf(
                navArgument(EMAIL) {
                    type = NavType.StringType
                    defaultValue = ""
                },
                navArgument(PHONE) {
                    type = NavType.StringType
                    defaultValue = ""
                },
                navArgument(IS_REDIRECT_FROM_LOGIN_OR_SPLASH) {
                    type = NavType.BoolType
                    defaultValue = false
                }
            )
        ) { backStackEntry ->

            VerificationPhoneCodeRoute(
                navHostController,
                sharedViewModel,
                userPhone = backStackEntry.arguments?.getString(PHONE),
                userEmail = backStackEntry.arguments?.getString(EMAIL),
                isRedirectFromLoginOrSplash = backStackEntry.arguments?.getBoolean(
                    IS_REDIRECT_FROM_LOGIN_OR_SPLASH
                )
            )
        }

For example, when startDestination comes with parameters, it looks like this:

 "${RegisterScreen.SignUpVerificationPhoneCodeScreen.route}?$IS_REDIRECT_FROM_LOGIN_OR_SPLASH=true"

it gives this error

java.lang.IllegalArgumentException: navigation destination verification_phone_code_screen?isRedirectFromLoginOrSplash=true is not a direct child of this NavGraph

Is there any way to solve this problem here? I want to send a parameter or value to verification_phone_code_screen that I can only check. I can do this another way, but I can't think of a solution. Most likely sending startDestination with parameters won't work. How can I do this in any way? Can you show me a solution? Please

0

There are 0 best solutions below