3
votes

I'm trying to learn jetpack compose and tried to make an easy app where you can add restaurants together with a score in an overview list using room.

However, everytime I try to type a word in the textfield, the textfield is not updated and remains empty. I would expect that updating the locationName in the onValueChange function would trigger an update of the state as it is part of a LiveData class. How can I solve this without having to make a seperate UI model in my modelView and having it converted to my entity object in case the data needs to be persisted?

My compose function


@Composable
fun AddItemScreenBody(modifier: Modifier = Modifier.Companion) {
    VerticalScroller {
        Column(modifier) {

                var locations = addItemViewNodel.location.observeAsState()
                FilledTextField(
                    value = locations.value!!.locationName,
                    onValueChange = { data -> locations.value!!.locationName = data },
                    label = { Text(stringResource(R.string.name), style = TextStyle(color = Color(0xFFC7C7C7))) })

            }

    }
}

My viewmodel

class AddItemViewModel () : ViewModel() {
    var location : LiveData<LocationEntity> = MutableLiveData(LocationEntity())

}

My data model

    @Entity(tableName = "locations")
    class LocationEntity @Ignore constructor () {
        @PrimaryKey(autoGenerate = true)
        var id: Long = 0
        @ColumnInfo(name = "location_name")
        var  locationName: String = "" 

        constructor (id: Long, locationName: String, category: Category) : this()
        {
            this.id = id
            this.locationName = locationName
        }

    }
3
Hey.. have you tried with @Model ?Madhav Gor
locations.value!!.locationName = data updating the value won't help instead you should call addItemViewNodel.location.setValue(new Instance of LocationEntity with desired locationName) Habib Kazemi

3 Answers

0
votes

With latest compose version (1.0.0-alpha09), for TextField section, you can do something like :

@Composable
fun MyTextField() {
Column(Modifier.padding(16.dp)) {
    val textFieldState = remember { mutableStateOf(TextFieldValue()) }
    TextField(
        value = textState.value,
        onValueChange = { textFieldState.value = it },
        onImeActionPerformed = { imeAction,controller ->
             if (imeAction == ImeAction.Done){
                 locations.value.locationName = textFieldState.value.text
                 controller?.hideSoftwareKeyboard()
             }
        }
    ) 
    Text("text field value is: ${textFieldState.value.text}")
}

Here, instead of saving data while user is typing, data will be saved when user has performed an action.

0
votes

Don't use Modifier.Companion, use Modifier only.

Don't use vertical scroller, use lazycolumn

Try this in your viewmodel

var _location = MutableLiveData(LocationEntity())
var location: LiveData<LocationEntity>
get() = _location

fun onLocationChange(data){
_locations.value!!. locationName = data //Confirm that u r doing it right.
}

Are you sure your room implementation is correct? No DAO, no repository?

Anyway try this out and let me know

0
votes

The answer of Habib Kazemi in the comments was the correct one and resolved the issue:

locations.value!!.locationName = data updating the value won't help instead you should call addItemViewNodel.location.setValue(new Instance of LocationEntity with desired locationName)