skip to Main Content

I am trying to figure out how I can create 2 different textfields (name and phone-number) in jetpack compose that when the user enters this type of info and press the continue button, the information will asynchronously save until the person is navigated/enters the "mainscreen". After the user enters the "mainscreen" in this case just a screen with a column saying hello, will the information be saved in mongoDatabase. How can I achieve this? Appreciate the help and feedback!

This is the code so far:

The screen with name, phonenumber and a continue button:

https://gyazo.com/12f15eac19a25f19c3ac1fea42820ab0

            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .weight(1f),
                verticalArrangement = Arrangement.Top,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {

                OutlinedTextField(
                    modifier = Modifier
                        .fillMaxWidth(0.80f),
                    value = name,
                    onValueChange = onNameChanged,
                    colors = OutlinedTextFieldDefaults.colors(
                        focusedBorderColor = LightBlue,
                    ),
                    label = {
                        Text(
                            text = "Name", // Goes top in a small text
                            color = LightBlue,
                            fontWeight = FontWeight.Bold
                        )
                    },
                    placeholder = {
                        Text(
                            text = "Enter your name", // Gives a hint to the user
                            color = Color.Black
                        )
                    },
                    singleLine = true,
                    leadingIcon = {
                        Icon(
                            imageVector = Icons.Default.Person,
                            contentDescription = null
                        )
                    },
                )

                Spacer(modifier = Modifier.height(10.dp))

                OutlinedTextField(
                    modifier = Modifier.fillMaxWidth(0.8f),
                    value = phoneNumber,
                    onValueChange = { phoneNumber = it },
                    keyboardOptions = KeyboardOptions.Default.copy(
                        keyboardType = KeyboardType.Number,
                        imeAction = ImeAction.Done
                    ),
                    keyboardActions = KeyboardActions(
                        onDone = {
                            // You can perform an action here when the user presses Done on the keyboard.
                            // For example, hide the keyboard.
                            keyboardController?.hide()
                        }
                    ),
                    singleLine = true,
                    textStyle = MaterialTheme.typography.bodyMedium.copy(fontSize = 16.sp),
                    colors = OutlinedTextFieldDefaults.colors(
                        focusedBorderColor = Color.Blue,
                        unfocusedBorderColor = Color.Gray
                    ),
                    label = {
                        Text(
                            text = "Phone Number", // Goes top in a small text
                            color = LightBlue,
                            fontWeight = FontWeight.Bold
                        )
                    },
                    placeholder = { Text(text = "Enter your telephone number") },

                    leadingIcon = {
                        Icon(
                            imageVector = Icons.Default.Phone,
                            contentDescription = null
                        )
                    },
                )

                Spacer(modifier = Modifier.height(10.dp))

            Button(
                modifier = Modifier
                    .wrapContentSize()
                    .fillMaxWidth(0.8f)
                    .height(80.dp)
                    .padding(start = 20.dp, end = 20.dp, bottom = 40.dp)
                    .align(Alignment.CenterHorizontally), // Align the button at the bottom center
                colors = ButtonDefaults.buttonColors(ConfirmButtonColor),
                shape = RoundedCornerShape(10.dp),
                onClick = {
                    if (name.isNotEmpty() && phoneNumber.isNotEmpty()) {
                        navController.navigate(AuthScreen.GenderProfile.route)

                    } else {
                        Toast.makeText(context, "Not all fields are filled-in!", Toast.LENGTH_SHORT).show()
                    }
                },
            ) {
                Text(
                    text = "Confirm",
                    color = Color.White,
                )
            }

Person Class:

class Person : RealmObject {
    @PrimaryKey
    var _id: ObjectId = ObjectId.invoke()
    var owner_id: String = ""

    // Profile
    var name: String = ""
    var phoneNumber: Int = 0

}

MongoRepository:

interface MongoRepository {
    fun configureTheRealm()
    fun getData(): Flow<List<Person>>
    suspend fun insertPerson(person: Person)
    suspend fun updatePerson(person: Person)
}

MongoDB Object:

object MongoDB : MongoRepository {
    private val app = App.create(APP_ID)
    private val user = app.currentUser
    private lateinit var realm: Realm

    init {
        configureTheRealm()
    }

    override fun configureTheRealm() {
        if (user != null) {
            val config = SyncConfiguration.Builder(
                user,
                setOf(Person::class)
            )
                .initialSubscriptions { sub ->
                    add(query = sub.query<Person>(query = "owner_id == $0", user.id))
                }
                .log(LogLevel.ALL)
                .build()
            realm = Realm.open(config)
        }
    }

    override fun getData(): Flow<List<Person>> {
        return realm.query<Person>().asFlow().map { it.list }
    }

    override suspend fun insertPerson(person: Person) {
        if (user != null) {
            realm.write {
                try {
                    copyToRealm(person.apply { owner_id = user.id })
                } catch (e: Exception) {
                    Log.d("MongoRepository", e.message.toString())
                }
            }
        }
    }

    override suspend fun updatePerson(person: Person) {
        realm.write {
            val queriedPerson =
                query<Person>(query = "_id == $0", person._id)
                    .first()
                    .find()
            if (queriedPerson != null) {
                queriedPerson.name = person.name
                queriedPerson.phoneNumber = person.phoneNumber
            } else {
                Log.d("MongoRepository", "Queried Person does not exist.")
            }
        }
    }
}

HomeViewModel:


class HomeViewModel : ViewModel() {
    var objectId = mutableStateOf("")
    var data = mutableStateOf(emptyList<Person>())

    // Profile + PickGender screen
    var name = mutableStateOf("")
    var phoneNumber = mutableStateOf(0)
    
    init {
        viewModelScope.launch {
            MongoDB.getData().collect {
                data.value = it
            }
        }
    }

    fun updateObjectId(id: String) {
        this.objectId.value = id
    }

    fun updateName(name: String) {
        this.name.value = name
    }

    fun updatePhoneNumber(phoneNumber: Int) {
        this.phoneNumber.value = phoneNumber
    }
    


    // The phoneNumber and Age will be set in string since I don't know how to set it in Int form
    fun insertPerson() {
        viewModelScope.launch(Dispatchers.IO) {
            if (
                name.value.isNotEmpty() &&
                phoneNumber.value.toString().isNotEmpty() &&
            ) {
                MongoDB.insertPerson(person = Person().apply {
                    name = [email protected]
                    phoneNumber = [email protected]

                })
            }
        }
    }

    fun updatePerson() {
        viewModelScope.launch(Dispatchers.IO) {
            if (objectId.value.isNotEmpty()) {
                MongoDB.updatePerson(person = Person().apply {
                    _id = ObjectId(hexString = [email protected])
                    name = [email protected]
                    phoneNumber = [email protected]

                })
            }
        }
    }

}

2

Answers


  1. Accessing and editing ViewModel variables from your views is a very bad practice. Here’s another way to temporarily save values till the user goes to the next screen: Use the remember API to save the states of the TextFields between recompositions. At the Button‘s click, you then call the save function you have at the ViewModel.

    var name by rememberSaveable { mutableStateOf("") }
    var phoneNumber by rememberSaveable { mutableStateOf("") }
    
    
    OutlinedTextField(
       value = name,
       onValueChange = { name = it },
       ...
    )
    
    Login or Signup to reply.
  2. MongoDB is a NoSQL database, and it does not require integration with Google Sign-In or email/password authentication for basic CRUD (Create, Read, Update, Delete) operations.

    If you are using MongoDB Realm, a serverless platform by MongoDB, you might be referring to the authentication methods it provides. Realm supports various authentication providers, including anonymous authentication, email/password, and OAuth 2.0 providers such as Google.

    You can enable anonymous authentication in MongoDB Realm if you don’t want to prompt users to provide credentials. This way, users can perform CRUD operations without signing in.

    Here’s an example of how you might use anonymous authentication with MongoDB Realm:

    1. Enable Anonymous Authentication in the MongoDB Realm Dashboard:
      Navigate to the Realm UI, find the "Authentication" section, and
      enable "Allow users to log in anonymously."
    2. Authenticate Anonymously in Your Android App: You can use the Realm SDK to log in anonymously:
        app.loginAsync(Credentials.anonymous()) {
            if (it.isSuccess) {
                Log.v("AUTH", "Successfully authenticated anonymously.")
                // You can now insert a person into the database
                insertPerson()
            } else {
                Log.e("AUTH", "Failed to authenticate anonymously.", it.error)
            }
        }```
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search