I have a problem with what I thought would be a si...
# compose
c
I have a problem with what I thought would be a simple example I tried to write up for compose. If you are well versed in mutableStateListOf I could use your help. Code in thread.
My composable is basically a helper/wrapper composable that is a password input field but also contains a list of "Validations" below it to show to the user
Copy code
data class Validations(val text: String, val validated: Boolean)

@Composable
fun PasswordVerifierInputField(
    value: String,
    change: (String) -> Unit,
    validations: List<Validations>
) {
    TextField(value = value, onValueChange = { change(it) })
    validations.forEach { Text(it.text, color = if (it.validated) Color.Green else Color.Red) }
}
This is the invoking code
Copy code
var myText by remember { mutableStateOf("") }

val myValidations =
    mutableStateListOf(
        Validations("8 chars", false), Validations("Special char", false))

PasswordVerifierInputField(
    myText,
    { update ->
        myText = update
        if (myText.isNotBlank()) {
            // switch first validation to true as an example
            myValidations[0] = myValidations[0].copy(validated = true)
        }
    },
    myValidations)
For some reason, the 0th place validation text doesn't change colors Also, does anyone have tips on whether I should keep Validations as a data class, or should that end up being a class that internally has 2 mutableStateOfs in it (one for text, and one for boolean)
n
Could it be due to not remembering the mutableStateListOf?
1
a
my first guess would be what nathan said. it seems like recomposing would cause you to reset your validations. as for the second question i would do it the way you have it currently. modeling your validation as a data model is the way to go imo
c
I tried remembering and now I get Type 'SnapshotStateList<Validations>' has no method 'setValue(Nothing?, KProperty<*>, [ERROR : Type from delegate])' and thus it cannot serve as a delegate for var (read-write property)
n
does it look something like below?
Copy code
val myValidations = remember { mutableStateListOf(
        Validations("8 chars", false), Validations("Special char", false)) }
c
Yep. Exactly that.
I actually just tried to make a list of strings just to see if the compile error had to do with Validations class, but even a list of strings isn't working?
Copy code
var myValidations by remember { mutableStateListOf("") }
Type 'SnapshotStateList<String>' has no method 'setValue(Nothing?, KProperty<*>, [ERROR : Type from delegate])' and thus it cannot serve as a delegate for var (read-write property)
My imports include the following
Copy code
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
n
change above to val and = instead of by
and see if that works
c
Yeah.
Copy code
val myValidations = remember { mutableStateListOf("") }
works
Oh sorry. I didn't notice your original code had that as well. My bad Updated mine to
Copy code
val myValidations = remember { mutableStateListOf(
        Validations("8 chars", false), Validations("Special char", false)) }
just now and it compiles! Time to test!
It works! Thanks! A few more questions if anyone is still around 1. If my mutableStateListOf validations is in my viewModel... I don't have to surround it with remember {}... right? 2. myValidations[0] = myValidations[0].copy(validated = true) seems kinda clunky. No better way than this I suppose?
n
Correct. Remember helps the values exist across recompositions. The view models are outside of this process.
👍 1
In regards to 2. Perhaps there is scope to use a derived state of that reads the current value and then checks the validation rules
Re why the = worked before it has to do with kotlin delegates (which i need to read up on more)
👍 1
c
@Nathan Castlehow alright thanks again for all the help. The question that started off this entire chain is actually that my team member is insisting that the composable actually takes care of the validations itself. It's a highly specific component and that state actually isn't needed anywhere else, so onValueChange we want to run the validators inline... but we get a ConcurrentModificationException. Any ideas why changing modifying in onValueChanged won't work?
I just gave up on trying to do the above ^ Bigger fish to fry and I guess I should really pass that event up anyway. /shruggie
263 Views