Allowing text input in multiple rows for a Kotlin Compose app

25 Views Asked by At

I can get it to work for one row, but when I try to put this into a loop where each row has a TextField in it, it doesn't work. When you type into the fields, you can't see any input there for example.

Here is the code I have

class WithdrawScreen: Screen {
@Composable
override fun Content() {
    val navigator = LocalNavigator.currentOrThrow
    val realm = openPelletRealm()
    val pelletLots: RealmResults<PelletLot> = retrieveAllPellotLots(realm)


    MaterialTheme {
//            var pelletsNeeded by remember { mutableStateOf("0") }

        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text("Withdraw Screen")

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(bottom = 20.dp),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                Text("Lot #")
                Text("# of Pellets")
                Text("Lot Date")
                Text("Size")
                Text("Pellets Needed")
            }

            val textFields = Array(pelletLots.size) { "" }

            for ((index, item) in pelletLots.withIndex()) {
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(bottom = 5.dp),
                    horizontalArrangement = Arrangement.SpaceEvenly
                ) {
                    Text(item.lotNumber)
                    Text(item.numberOfPelletsInLot.toString())
                    Text(convertLongDateToString(item.dateOfLot))
                    Text(item.pelletSize.toString())
                    TextField(
                        modifier = Modifier.padding(start = 5.dp).width(width = 50.dp),
                        value = textFields[index],  //<-- Problem here maybe?
                        onValueChange = { textFields[index] = it })  //<-- Or here?
                }
            }

            Spacer(modifier = Modifier.weight(1f))

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(bottom = 20.dp),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                Button(onClick = {
                    closePelletRealm(realm)
                    navigator.pop()
                }) {
                    Text("Back")
                }
            }
        }
    }
}

}

What am I doing wrong, please?

I think it's at one of the two lines I have commented on. The value or the onChangeValue lines need to be tweaked, but nothing I try there helps.

1

There are 1 best solutions below

1
Leviathan On

For your TextFields' value property to automatically update, what you assign to it must be wrapped in a MutableState. That is necessary for compose to be notified about any changes. Moreover, the textFields array must be remembered, so it doesn't get recreated with empty values when a recomposition takes place.

You could do it like this:

val textFields = remember { Array(pelletLots.size) { mutableStateOf("") } }
...
TextField(
    value = textFields[index].value,
    onValueChange = { textFields[index].value = it }
)