How to clear textfield value in Jetpack Compose?

Viewed 3714

I've developed a textInput composable with a trailing icon, and I'd like to clear the textInput when the icon is clicked. How can I access the textInput value, so that I can clear it?

    @Composable
fun TextInput(
    myVal: String,
    label: String,
    placeholder: String="",
    helperText: String="",
    errorText: String="",
    onValueChange : (String) -> Unit){
    val hasError = !errorText.isNullOrEmpty()
    val helperColor =  if (hasError)
        Color(0xFFfe392f)
        else
            Color(0xFF5c6a79)

    Row() {
            Column() {
                TextField(
                    colors = TextFieldDefaults.textFieldColors(
                        backgroundColor = Color.Transparent,
                        textColor = Color(0xFF011e41),
                        cursorColor = Color(0xFF011e41),
                        focusedLabelColor = Color(0xFF011e41),
                        unfocusedLabelColor = Color(0xFF011e41),
                        unfocusedIndicatorColor = Color(0xFFebeced),
                        focusedIndicatorColor = Color(0xFF011e41),
                        errorCursorColor = Color(0xFFfe392f),
                        errorIndicatorColor = Color(0xFFfe392f),
                        errorLabelColor = Color(0xFFfe392f)
                    ),
                    value = myVal,
                    onValueChange = onValueChange,
                    label = { Text(label) },
                    placeholder = { Text(placeholder) },
                    isError = hasError,
                    trailingIcon = {Icon(Icons.Filled.Email, contentDescription = "sdsd", modifier = Modifier.offset(x= 10.dp).clickable {
                       //What should I do here?
                    })}
                )

                Text(
                    modifier = Modifier.padding(8.dp),
                    text = if (hasError) errorText else helperText,
                    fontSize = 12.sp,
                    color = helperColor,
                )
            }
    }
}

it's used like this:

var text by remember { mutableStateOf("") }
                    TextInput(myVal = text, label = "label", helperText = "", errorText = "my error") {text = it}
4 Answers

You can use the trailingIcon attribute with a custom clickable modifier.
Something like:

var text by rememberSaveable { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = { text = it },
    trailingIcon = {
        Icon(Icons.Default.Clear,
            contentDescription = "clear text",
            modifier = Modifier
                .clickable {
                    text = ""
                }
        )
    }
)

enter image description here

If you are using a TextFieldValue:

val content = "content"
var text by rememberSaveable(stateSaver = TextFieldValue.Saver) {
    mutableStateOf(TextFieldValue(content))
}

TextField(
    value = text,
    onValueChange = { text = it },
    trailingIcon = {
        Icon(Icons.Default.Clear,
            contentDescription = "clear text",
            modifier = Modifier
                .clickable {
                    text = TextFieldValue("")
                }
        )
    }
)

the click handler of your trailing icon has to call the TextField's onValueChange with an empty string:

       ...
       trailingIcon = {Icon(Icons.Filled.Email, contentDescription = "sdsd", modifier = Modifier.offset(x= 10.dp).clickable {
           onValueChange("") // just send an update that the field is now empty
       })}
       ...

This shall achieve this

//Caller
val text by remember { mutableStateOf (...) }

TextInput(text, ..., ...,)

//Composable
@Composable
fun TextInput(text, ..., ...){
val textState by remember { mutableStateOf (text) }
TextField(
 value = textState,
trailingIcon = {
 Icon(..., Modifier.clickable { textState = "" })
}
}

Use trailingIcon Composable property with IconButton to match the background selector of the icon with the rest of the theme. You can also put empty condition to display it only when there is some input in the text field.

Below is sample code snippet:

var text by remember { mutableStateOf ("") }

TextField(
    trailingIcon = {
        when {
            text.isNotEmpty() -> IconButton(onClick = {
                text = ""
            }) {
                Icon(
                    imageVector = Icons.Filled.Clear,
                    contentDescription = "Clear"
                )
            }
        }
    }
)
Related