Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

SimpleAlertDialog component in Jetpack Compose cannot be added to a DetailView due to context of @Composable

I was developing an app where I’m using Jetpack Compose as UI developing tool, and I design some kind of custom AlertDialog, which is the following:

CustomAlertDialog.kt


@Composable
fun SimpleAlertDialog(
    hero: CharacterModel? = null,
    show: Boolean,
    onConfirm: () -> Unit,
    onDismiss: () -> Unit,
    textDescription: String,
    textTittle: String,
) {
    if(show){
        AlertDialog(
            onDismissRequest = onDismiss,
            confirmButton = {
                TextButton(onClick = onConfirm)
                { Text(text = "OK") }
            },
            dismissButton = {
                TextButton(onClick = onDismiss)
                { Text(text = "Cancel") }
            },
            title = { Text(text = textTittle) },
            text = { Text(text = textDescription) }
        )
    }
}

But when I try to use in a detailScreen, I get the following context Composable error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

@Composable invocations can only happen from the context of a @Composable function

the region of code where I try to instances the following, where I get the error:


@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MyCharactersListRowView(
    viewmodel: MainViewModel,
    characterModel: CharacterModel,
    popBack: () -> Unit
) {
    val (characterSelected, setCharacterSelected) = remember { mutableStateOf<CharacterModel?>(null) } //HOOK FUNCTION
    val openDialog = remember { mutableStateOf(false) }

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = { setCharacterSelected(characterModel) })
            .padding(vertical = 8.dp, horizontal = 16.dp),
        verticalAlignment = Alignment.CenterVertically
    ){
        AsyncImage(
            model = characterModel.image,
            contentDescription = characterModel.name,
            contentScale = ContentScale.Fit,
            modifier = Modifier
                .size(60.dp)
                .clip(CircleShape)
                .combinedClickable(
                    onLongClick = {
                        if (characterSelected != null) {
                            SimpleAlertDialog(
                                hero = characterSelected,
                                show = true,
                                onConfirm = {
                                    viewmodel
                                        .deleteCharacter(characterSelected!!.id.toLong())
                                        .also {
                                            Log.d(
                                                "info",
                                                "rowAffected: ${viewmodel.rowAffected.value}"
                                            )
                                            if (viewmodel.rowAffected.value.toInt() != 0) {
                                                Toast
                                                    .makeText(
                                                        LocalContext.current!!,
                                                        "¡ ${characterSelected.name} bought sucessfully!",
                                                        Toast.LENGTH_LONG
                                                    )
                                                    .show()
                                                    .also {
                                                        openDialog.value = false
                                                    }
                                            } else {
                                                Toast
                                                    .makeText(
                                                        LocalContext.current!!,
                                                        viewmodel.loadError.value,
                                                        Toast.LENGTH_LONG
                                                    )
                                                    .show()
                                                    .also {
                                                        openDialog.value = false
                                                    }
                                            }
                                        }
                                },
                                onDismiss = { openDialog.value = false },
                                textTittle = "Remove character",
                                textDescription = "Would you like to remove ${characterSelected.name} from your characters?"
                            )
                        } else {

                        }
                    },
                    onClick = {
                        //TODO {Do something}
                    }
                )
        )

...

...

So I know is a quite beginner error, but I’ve not been able to get into a working solution, due to take thanks in advance is you know how implement it.

>Solution :

You can’t call a Dialog from a lambda that doesn’t have @Composable annotation. You can check this answer out for differences between Composable and non-Composable functions.

fun Modifier.combinedClickable(
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    onLongClickLabel: String? = null,
    onLongClick: (() -> Unit)? = null,
    onDoubleClick: (() -> Unit)? = null,
    onClick: () -> Unit
) 

These lambdas are not @Composable

Common way for showing dialog in Jetpack Compose is

var showDialog by remember {mutableStateOf(false)}

if(characterSelected && showDialog) {
  SimpleAlertDialog(onDismiss={showDialog = false})
}

and change showDialog to true inside long click

onLongClick = {
  showDialog = true
}

Show custom alert dialog in Jetpack Compose

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading