Skip to content

A form validation library for Kotlin Multiplatform, primarily intended for use with Compose Multiplatform

License

Notifications You must be signed in to change notification settings

windedge/viform-multiplatform

Folders and files

NameName
Last commit message
Last commit date

Latest commit

4337123 · Jan 12, 2025

History

51 Commits
Dec 21, 2023
Jan 12, 2025
Jan 12, 2025
Dec 21, 2023
Jan 12, 2025
Jan 12, 2025
Jul 4, 2023
Dec 21, 2023
Jul 4, 2023
Jan 12, 2025
Jul 4, 2023
Dec 19, 2023
Jan 7, 2024
Dec 21, 2023
Dec 21, 2023
Jan 12, 2025
Nov 30, 2023
Jul 4, 2023
Jul 4, 2023
Dec 12, 2023

Repository files navigation

English | 中文

ViForm

ViForm is a Kotlin library for form validation, mainly aimed at Compose Multiplatform projects. It has the following features:

  • Supports Kotlin Multiplatform(android, jvm, js/wasmjs, native)
  • Type-safe validation rules, supporting both DSL style and chained style validation declaration
  • Form state management
  • Integrated support for Compose Multiplatform(android, desktop, wasmjs)

Prerequisites

  • Kotlin Coroutine
  • KopyBuilder
  • Compose Multiplatform (optional)

Installation

Apply the KopyBuilder Gradle plugin

plugins {
    id("io.github.windedge.kopybuilder") version "0.1.5"
}

Add dependency to Multiplatform project

kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("io.github.windedge.viform:viform-core:$VERSION")

                // Optional
                implementation("io.github.windedge.viform:viform-compose:$VERSION")
            }
        }
    }
}

Add dependency to JVM project

dependencies {
    implementation("io.github.windedge.viform:viform-core:$VERSION")

    // Optional
    implementation("io.github.windedge.viform:viform-compose:$VERSION")
}

Quick Start

Define validation rules:

import io.github.windedge.copybuilder.KopyBuilder
import io.github.windedge.viform.core.*


@KopyBuilder
data class Signup(
    val name: String = "",
    val email: String? = null,
    val password: String = "",
    val confirmPassword: String = "",
)


val schema = FormSchema.create<Signup> {
   field(Signup::name) {
       required("User name is required.")
       isAlphaNumeric()
   }

   field(Signup::email).optional {
       isEmail()
   }

   // Chain style
   field(Signup::password).required().lengthBetween(8, 20)

   // Custom rule
   field(Signup::confirmPassword).required().lengthBetween(8, 20)
       .custom("Passwords must be the same.") {
           it == field(Signup::password).currentValue
       }
}

Use in Jetpack Compose project:

import io.github.windedge.viform.compose.use

@Compose
fun SignupApp() {
    val form = schema.buildForm(Signup())
    Column {
        form.use {
            field(it::name) {
                TextInput("User Name: ", currentValue, hasError, errorMessage, onValueChange = {
                    setValue(it, validate = true)  // validate synchronously
                })
            }

            field(it::email) {
                watchLazily { validate() }  // validate asynchronously
                TextInput("Email:", currentValue ?: "", hasError, errorMessage, onValueChange=::setValue)
            }

            field(it::password) {
                watchLazily { if (it.isNotEmpty()) validate() }
                TextInput("Password:", currentValue, hasError, errorMessage, onValueChange=::setValue)
            }

            field(it::confirmPassword) {
                watchLazily { if (it.isNotEmpty()) validate() }
                TextInput("Confirm Password:", currentValue, hasError, errorMessage, onValueChange=::setValue)
            }

            // validate on submit
            Button(onClick = {
                if(form.validate()) {
                    val signup = form.pop()   // get form data
                    // ...
                }
            }) { Text("Sign up") }
        }
    }
}

License

MIT License

Author

Ken Xu