Skip to content

Android library to help validate forms without going insane!

Notifications You must be signed in to change notification settings

MahmoudAlyuDeen/ValidatableForm

Repository files navigation

Read the story

Validate Forms on Android Without Losing Your Mind

See it in action

Sample APK

app-debug.apk

Demo video

https://www.youtube.com/watch?v=SMSCVwfZsc4

Add to your project

Kotlin

implementation("com.github.mahmoudalyudeen:validatableform:1.0.1")

Groovy

implementation 'com.github.mahmoudalyudeen:validatableform:1.0.1'

Quick usage

Field

To Define an input, use a Field

val username = Field<String>(initialValue = "", validator = { it.isNotBlank() })

Or you can skip the explicit type and argument names

val username = Field("") { it.isNotBlank() }

A field can have any type. It doesn't have to be a String.

To set the value of the field

username.value = "awesome user"

Or in a ViewModel, you can do something like this

fun onPasswordChanged(password: CharSequence) {
    _loginForm.password.value = password.toString()
}

To get the value of the field

val usernameStr: String = username.value

Or by databinding

<EditText
    ..
    android:text="@{loginViewModel.loginForm.username.toString()}" />

Don't forget adding toString()

To evaluate the validity of the field

val isUsernameValid: Boolean = username.valid

Forms

To define a form, create a class extending ValidatableForm.

And override fields and pass a list of all the fields you want to validate.

class LoginForm : ValidatableForm() {
   val username = Field(initialValue = "") { it.isNotBlank() }
   val password = Field(initialValue = "") { it.length >= 6 }
   val agreeTos = Field(initialValue = false) { it }
   
   override val fields = listOf(username, password, agreeTos)
}

Then create an instance of that class in your ViewModel with a backing property to allow access and prevent modification

private val _loginForm = LoginForm()
val loginForm: LoginForm
    get() = _loginForm

To evaluate the validity of entire form

val isLoginValid: Boolean = loginForm.valid

Or by databinding

<Button
    ..
    android:enabled="@{loginViewModel.loginForm.valid}" />

Validator

A field is created with a validator; a lambda function that takes the value of the field as its input and returns true when it's valid.

Validator examples

String

validator = { it.isNotBlank() }

validator = { it.length >= 6 }

Boolean

validator = { it } or validator = { !it }

Int

validator = { it > 5 }

Custom type

data class Birthday(
    val day: Int? = null,
    val month: Int? = null,
    val year: Int? = null
) {
    val valid
        get() = day != null && month != null && year != null
}

val birthday = Field(Birthday()) { it.valid }

Referencing other fields

val password = Field("") { it.length >= 6 }

val passwordConfirmation = Field("") { it == password.value }

Field without validation (optional)

 val optionalField = Field("") { true } 

Usage with EasyValidation

EasyValidation is a validation library with very helpful extension functions to check for valid emails, phone numbers and passwords.

val email = Field("") { it.validEmail() }

LiveData and Transformations

If you want to use Transformations.map()/.switchMap()

val loginText = map(_loginForm.username.valueLive) { "Welcome back $it" }

Databinding + TextInputLayout

Like the example app, you can create a binding adapter to set the helper text or error for a TextInputLayout

HelperText Example

LoginBindingAdapters

About

Android library to help validate forms without going insane!

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages