Skip to content

Custom rules

A rule is anything implementing ValueValidatorRule<V> — return a ValidationResult from validate(value). For the rules that already ship, see built-in rules; to run an existing rule only sometimes, see onlyWhen.

Reusable rule types

// A reusable rule: an object (or data class for parameterised rules) implementing
// ValueValidatorRule<V>. Return success for blank input — let Required own emptiness.
data object UsZipCode : ValueValidatorRule<String> {
    private val zip = Regex("""^\d{5}(-\d{4})?$""")
    override fun validate(value: String): ValidationResult {
        if (value.isBlank()) return RegularValidationResult.success()
        return if (zip.matches(value)) RegularValidationResult.success()
        else RegularValidationResult.error("Enter a valid ZIP code")
    }
}

Use a data class instead of data object when the rule takes parameters (MinLength(minLength = 8) is built that way).

One-off rules (SAM lambdas)

// ValueValidatorRule is a fun interface — one-off rules can be inline SAM lambdas.
// Severity is graded: error/warning/info/success all flow through supportingText.
val NoPlusAddressing = ValueValidatorRule<String> { value ->
    if ("+" in value) RegularValidationResult.warning("Plus-addressing may break receipts")
    else RegularValidationResult.success()
}

Severities and results

ValidationResult.outcome() ranks ERROR > WARNING > INFO > SUCCESS. Only ERROR blocks validate()/submission — warnings and info messages display through supportingText without failing the field.

Two result implementations ship with the library:

  • RegularValidationResult.error/warning/info/success("message") — plain strings, shown verbatim
  • ResourceValidationResult — backed by Compose StringResource for i18n; all the built-in rules use this

Conventions

  • Return success for blank input and let Required own emptiness — that way every rule composes with optional fields (listOf(UsZipCode) allows blank, listOf(Required, UsZipCode) doesn't).
  • Rules run on every value change; keep validate cheap and side-effect free.