I'm doing validation on an EditText. I want the CharSequence to be invalid if it's empty or it doesn't begin with "https://". I'm also using RxBinding, specifically RxTextView. The problem is that when there is one character left, and I then delete it leaving no characters left in the the CharSequence the map operator doesn't fire off an emission. In other words I want my map operator to return false when the EditText is empty. I'm beginning to think this may not be possible the way I'm doing it. What would be an alternative?
Here is my Observable / Disposable:
val systemIdDisposable = RxTextView.textChanges(binding.etSystemId)
.skipInitialValue()
.map { charSeq ->
if (charSeq.isEmpty()) {
false
} else {
viewModel.isSystemIdValid(charSeq.toString())
}
}
.subscribe { isValid ->
if (!isValid) {
binding.systemIdTextInputLayout.isErrorEnabled = true
binding.systemIdTextInputLayout.error = viewModel.authErrorFields.value?.systemId
} else {
binding.systemIdTextInputLayout.isErrorEnabled = false
binding.systemIdTextInputLayout.error = viewModel.authErrorFields.value?.systemId
}
}
And here is a function in my ViewModel that I pass the CharSequence to for validation:
fun isSystemIdValid(systemId: String?): Boolean {
return if (systemId != null && systemId.isNotEmpty()) {
_authErrors.value?.systemId = null
true
} else {
_authErrors.value?.systemId =
getApplication<Application>().resources.getString(R.string.field_empty_error)
false
}
}
After sleeping on it, I figured it out.
I changed
RxTextView.textChangestoRxTextView.textChangeEvents. This allowed me to query theCharSequence's text value (usingtext()method provided bytextChangeEvents) even if it's empty. Due to some other changes (not really relevant to what I was asking in this question) I was also able to reduce some of the conditional code too. I'm just putting that out there in case someone comes across this and is curious about these changes. The takeaway is that you can get that empty emission usingRxTextView.textChangeEvents.Here is my new Observer:
And here is my validation code from the ViewModel:
Lastly, if anyone is curious about how I'm using my LiveData / MutableLiveData objects; I create a private MutableLiveData object and only expose an immutable LiveData object that returns the values of the first object. I do this for better encapsulation / data hiding. Here is an example:
Hope this helps someone!