Reputation: 1152
I have a TextField component that I want to set the initial content to. The initial content will be fetched from a database using a Flow.
I have this TextField
code (loosely following this codelabs tutorial):
@Composable
private fun EntryText(placeholder: String, initialText: String = "", ) {
val (text, setText) = remember { mutableStateOf(initialText) }
EntryTextField(
text = text,
placeholder = placeholder,
onTextChanged = setText
)
}
and
@Composable
private fun EntryTextField(text: String, placeholder: String, onTextChanged: (String) -> Unit) {
TextField(
modifier = Modifier.fillMaxWidth(),
value = text,
onValueChange = {
onTextChanged(it)
},
placeholder = { Text(text = placeholder) }
)
}
I want use it like so to set both a Text
and the content of the EntryText
:
val entry by viewModel.getEntryContent().collectAsState(initial = "initial")
val hint = "hint"
Column {
Text(text = entry)
EntryText(placeholder = hint, initialText = entry)
}
When the ViewModel getEntryContent
flow emits the result from the database only the Text
is being updated with the new String and not the EntryText
(it stays with the initial state of "initial"
).
How can I have my TextField get updated when my ViewModel emits the string?
Upvotes: 6
Views: 3903
Reputation: 60963
Because your text is handle by ViewModel
, I think you can store it state in ViewModel
like
class MainViewModel : ViewModel() {
var entry = MutableStateFlow("initial")
fun getEntryContent(): Flow<String> {
// get from database
}
}
In your Activity
val entry by viewModel.entry.collectAsState()
Column {
Text(text = entry)
EntryText(placeholder = hint, text = entry, onTextChanged = {
viewModel.entry.value = it
})
}
lifecycleScope.launch {
viewModel.getEntryContent().flowWithLifecycle(lifecycle).collect {
// observe value from db then set to TextField
viewModel.entry.value = it
}
}
Upvotes: 1