Home > Back-end >  List search inside viewModel issue in Jetpack Compose
List search inside viewModel issue in Jetpack Compose

Time:09-17

I am trying to make a name search functionality in a Compose project. I have a list of DummyClient, which I am using as my data source on a view model. I am trying to search this list, so the updated result can be shown on a LazyColumn, which is not returning any error but providing unexpected results.

class ClientViewModel : ViewModel() {
    private var _clients = MutableLiveData(dummyClients)
    val clients: LiveData<List<DummyClient>>
        get() = _clients

    fun searchClients(name: String) {
        val foundClients: List<DummyClient?> = listOf(dummyClients.find {
            it.name.contains(name)
        })
        _clients.value === foundClients
    }
}

This ViewModel is passed to the ClientDirectoryScreen composable from the navigation, which displays a search bar and the client list on a LazyColumn:

val clientViewModel: ClientViewModel = ViewModel()
...
composable(Screen.Clients.route) {
    ClientDirectoryScreen(
        ...
        clientViewModel = clientViewModel
    )
}
@Composable
fun ClientDirectoryScreen(
    ...
    clientViewModel: ClientViewModel
) {
    val clients by clientViewModel.clients.observeAsState(listOf())
    val showSearchBar by clientViewModel.showSearchBar.observeAsState(false)

    if (clients.isNotEmpty()) {
        Column {

            // show the search bar on search icon click
            if (showSearchBar) ClientSearchCard(clientViewModel)

            LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp)) {
                items(clients) { client ->
                    ClientNameCard(client)
                }
            }
        }
    }
}

And the search bar invokes the search in the ViewModel, which doesn't reflect the search:

@Composable
fun ClientSearchCard(clientViewModel: ClientViewModel) {
    var searchText by remember { mutableStateOf("") }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        TextField(
            value = searchText,
            onValueChange = {
                searchText = it
                clientViewModel.searchClients(searchText)
            },
            label = { Text("Search:") },
            modifier = Modifier.fillMaxWidth()
        )
    }
}

If I log the search result in the view model, the search doesn't provide the correct result. Also, I don't see any state change for the clients variable in ClientDirectoryScreen.

CodePudding user response:

find will return you only one element, and the result is optional, because collection may have none.

Instead you can use filter on the collection: it'll return all matching elements:

val foundClients = dummyClients.filter {
    it.name.contains(name)
}
_clients.value = foundClients
  • Related