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.

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:

400: Invalid request

And Nel is a NotEmptyList that will aggregate errors.

Validated has two possible values: Valid and Invalid and we will use the as following:





Mail









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.

400: Invalid request

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

400: Invalid request

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>>

400: Invalid request

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.

400: Invalid request

Fold

Once again we are using method reference with the following methods:

400: Invalid request

400: Invalid request

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.

You can find here the implementation using Either