Home > other >  How would I disable a Jetpack Compose save/add/submit button to prevent a duplicate item being added
How would I disable a Jetpack Compose save/add/submit button to prevent a duplicate item being added

Time:12-23

I want to use a simple TextField widget in JetPack Compose code along with a Save button. When Save is clicked the text will be added to a list. If the text is already in the list, I would like to disable the Save button and highlight the text is red to flag a potential error condition. How could this be done?

CodePudding user response:

This has the logic in the composable itself, you'd want to move it to a viewmodel, but it should set you on the right path

val items = remember {
    mutableStateListOf<String>()
}
var item by remember { mutableStateOf("") }
var isError by remember { mutableStateOf(false) }
LaunchedEffect(key1 = Unit) {
    combine(
        snapshotFlow { items },
        snapshotFlow { item }
    ) { items, query ->
        items.contains(query)
    }
        .onEach { isError = it }
        .launchIn(this)
}
Column(
    modifier = Modifier
        .fillMaxSize()
        .padding(all = 16.dp)
) {
    TextField(
        value = item,
        onValueChange = {
            item = it
        },
        modifier = Modifier.fillMaxWidth()
    )
    Button(
        onClick = {
            items.add(item)
            item = ""
        },
        enabled = !isError,
        modifier = Modifier.padding(top = 16.dp),
    ) {
        Text(text = "Save item")
    }
}

Edit: you can simplify a bit with derivedStateOf

val items = remember {
    mutableStateListOf<String>()
}
var item by remember { mutableStateOf("") }
val isError = remember {
    derivedStateOf {
        items.contains(item)
    }
}
Column(
    modifier = Modifier
        .fillMaxSize()
        .padding(all = 16.dp)
) {
    TextField(
        value = item,
        onValueChange = {
            item = it
        },
        modifier = Modifier.fillMaxWidth()
    )
    Button(
        onClick = {
            items.add(item)
            item = ""
        },
        enabled = !isError.value,
        modifier = Modifier.padding(top = 16.dp),
    ) {
        Text(text = "Save item")
    }
}

CodePudding user response:

It is just an example (you should use a ViewModel):

var text by remember { mutableStateOf("") }
var list = remember { mutableStateListOf<String>()}

val isInList = remember {
    derivedStateOf {
        list.contains(text)
    }
}.value

Row() {
    TextField(
        value = text,
        onValueChange = {
            text = it
        },
        colors = TextFieldDefaults.textFieldColors(
            textColor = if (isInList) Red else Black,
        )
    )

    Button(
        onClick = { list.add(text) },
        enabled= !isInList,
    ){
        Text("Save")
    }

}
  • Related