skip to Main Content
fun TextFieldWithIconsAndErrorLabel(
    text: String,
    charLimit: Int = Int.MAX_VALUE,
    keyboardType: KeyboardType = KeyboardType.Text,
    onValueChange: (String) -> Unit,
) {
    val keyboardController = LocalSoftwareKeyboardController.current
    var shouldShowMaxCharLimitError by remember { mutableStateOf(false) }

    BasicTextField(
        modifier = Modifier
            .fillMaxWidth(),
        value = text,
        onValueChange = { newInput ->
            if (newInput.length > charLimit) {
                shouldShowMaxCharLimitError = true
            } else {
                shouldShowMaxCharLimitError = false
                onValueChange(newInput)
            }
        },
        keyboardOptions = KeyboardOptions(
            imeAction = ImeAction.Done,
            keyboardType = keyboardType,
        ),
        singleLine = true,
        keyboardActions = KeyboardActions(
            onDone = {
                keyboardController?.hide()
                onValueChange(text)
                shouldShowMaxCharLimitError = false
            }
        ),
    )
    if (shouldShowMaxCharLimitError) {
        Text(
            modifier = Modifier
                .fillMaxWidth(),
            text = "Max character limit exceeded",
            style = TextStyle(
                fontFamily = PoppinsFamily,
                fontWeight = FontWeight.Medium,
                fontSize = 12.sp,
                color = Color.Red,
                textAlign = TextAlign.Start
            ),
        )
    }
}

In the above code, onValueChange is called multiple times and immediately resets the boolean.
For every text input, this lambda get invoked twice.

onValueChange = { newInput ->
            if (newInput.length > charLimit) {
                shouldShowMaxCharLimitError = true
            } else {
                shouldShowMaxCharLimitError = false
                onValueChange(newInput)
            }
        }

2

Answers


  1. change your onValueChange to this

    onValueChange = { newInput ->
            shouldShowMaxCharLimitError = newInput.length > charLimit
            if (!shouldShowMaxCharLimitError) {
                onValueChange(newInput)
            }
        }
    

    and remove the call to onValueChange(text) inside the onDone callback

    onDone = {
        keyboardController?.hide()
        // Remove the following line
        // onValueChange(text)
        shouldShowMaxCharLimitError = false
    }
    
    Login or Signup to reply.
  2. You should add

    var textValue by remember { mutableStateOf(text) }
    

    result:

    var textValue by remember { mutableStateOf(text) }
    
    BasicTextField(
        modifier = Modifier
            .fillMaxWidth(),
        value = textValue,
        onValueChange = { newInput ->
            if (newInput.length > charLimit) {
                shouldShowMaxCharLimitError = true
            } else {
                shouldShowMaxCharLimitError = false
                onValueChange(newInput)
            }
            textValue = newInput
        },
        keyboardOptions = KeyboardOptions(
            imeAction = ImeAction.Done,
            keyboardType = keyboardType,
        ),
        singleLine = true,
        keyboardActions = KeyboardActions(
            onDone = {
                keyboardController?.hide()
                onValueChange(text)
                shouldShowMaxCharLimitError = false
            }
        ),
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search