This is the last post of the Functional Validation serie and we are going to use Validated, our last data type.
Validated is like Either with some additional power, and using it we can finally aggregate all errors and give proper feedback to our users.
Let’s use Validated
Like Either, Validated will contain two possible values, one when the data is invalid, and one when the data is valid. But this time we are going to use different types.
We will use
-
Validated<Nel<ValidationError>, String>
for email -
Validated<Nel<ValidationError>, String>
for phone numbers -
Validated<Nel<ValidationError>, Data>
for the whole form
ValidationError is a sealed class used to define all possible errors:
And Nel is a NotEmptyList that will aggregate errors.
Validated has two possible values: Valid and Invalid and we will use the as following:
Phone Number
Once again we will use kotlin extension methods invoking validMail and validNumber functions we have discussed in the first post to build our instances.
if the validation function returns true we will wrap the value using the .valid() method, otherwise we will create a Nel with the correct error and wrap it using the .invalid() method.
Map them
By now we are experts of map, let’s use it
Using Validated our map finally has the desired behaviour and we get all input errors in the list:
Android UI
In our ViewModel we will use the previously discussed code to update a <Validated<Nel<ValidationError>, Data>>
In the activity we retrieve the viewModel, register click listener and observe the result of the validation. Once we get the result we clear previous errors and then fold it.
Fold
Once again we are using method reference with the following methods:
In the invalid path we using kotlin when
to find the correct error message and TextInputLayout to notify the user, while in the valid path we just show data to user.