How can i change value in TextField value from viewModel in jetpack compose
Asked Answered
B

2

11

I am using in my project, and don't know how to change a TextField's value from my ViewModel.

In my Activity:

...
@Composable
fun myView() {
    var dName = remember {
        mutableStateOf(TextFieldValue(""))
    }
    TextField(
        value = dName.value, 
        onValueChange = { dName.value = it }, 
        modifier = Modifier.fillMaxWidth()
    )
}
...

In my ViewModel:

...
var dName = MutableStateFlow("")
...

I want to call dName.value = "test" in my ViewModel and change the shown value in the TextField. How can I accomplish this?

Bob answered 22/12, 2021 at 9:28 Comment(0)
V
12

You can also use mutableStateOf instead of MutableStateFlow. I think it much simple.

ViewModel

var dname by mutableStateOf("init value")

Composable

TextField(
    value = viewModel.dname,
    onValueChange = { viewModel.dname = it }
)

In ViewModel, when you want to change the value, you can call dname = "test"

Vigor answered 8/1, 2022 at 1:56 Comment(2)
out of interest, is this also acceptable in the viewmodel: var textFieldValue by mutableStateOf(TextFieldValue())?Sulfanilamide
Note that we don't use remember and viewModel.dname.value. You don't have to use onValueChange if you just print new value.Digest
L
6

Assuming you have a reference to your viewModel called viewModel, you just have to call viewModel.name.collectAsState(). But beyond that, I suggest keeping the data logic in the ViewModel, by making the MutableStateFlow private and exposing an immutable StateFlow and a setter method to the composable.

// ViewModel
private val _name = MutableStateFlow("")
val name = _name.asStateFlow()

fun setName(name: String) {
  _name.value = name
}
// Composable
val name = viewModel.name.collectAsState()
TextField(
  value = name,
  onValueChange = viewModel::setName
)

As you can see, I'm not using remember { mutableStateOf(...) } here, because the StateFlow in the ViewModel is the single source of truth.

Your approach of setting the composable's value imperatively doesn't make sense in the declarative API that Jetpack Compose provides.

Try reading up on declarative/imperative UI and state in Jetpack compose as well as kotlin flow to learn more.

Lepp answered 24/12, 2021 at 16:15 Comment(4)
Thanks, According to your modification it runs very wellBob
_name come from??? I don't your dialect of english.Madden
From the official docs: developer.android.com/jetpack/compose/text#state-mgmt Avoid using reactive streams like StateFlow to represent your TextField state, as these structures introduce asynchronous delays. Instead, use MutableStateSulfanilamide
This is a rare occasion where an answer is 100% correct and with the best practices. This should be mark as a answer.Encephalograph

© 2022 - 2024 — McMap. All rights reserved.