StatefulValidation
Validation for values of type T where the form manager maintains a validation state of type TState for each managed value.
Stateful validations are useful when validations require an expensive computation over data and if it is possible to save the result of such expensive computation and tweak it as data changes instead of running the expensive computation all over again.
As an example, imagine that we have a list of people and that we want to validate that the average age of all people isn't over a certain age. Instead of iterating over the whole list every time a person is added or removed, we can use a stateful validation to save, as state, the sum of all ages, and simply tweak this sum as people are added or removed. Having access to the sum of all ages as state allows us to implement the validation function with a complexity of O(1) as opposed to O(N).
The following snippet implements the example above of making sure that the average age of all people doesn't surpass a dependency maxAvgAge:
object AvgAgeNotOverMax : StatefulValidation<List<Person>, Int>() {
private val ValidationContext.maxAvgAge: Int by dependency("../maxAvgAge")
override suspend fun ValidationContext.initState(value: List<Person>): Int =
value.fold(0) { sum, person -> sum + person.age }
private val ageObserver by observe<Int>("∗/age") { agesSum, event ->
when (event) {
is ValueEvent.Init<Int> -> agesSum + event.newValue
is ValueEvent.Change<Int> -> agesSum + event.newValue - event.oldValue
is ValueEvent.Destroy<Int> -> agesSum - event.oldValue
else -> agesSum
}
}
override fun ValidationContext.validateFromState(value: List<Person>, state: Int) = flow {
val avgAge = state / value.size
if (avgAge > maxAvgAge) {
emit(ValidationError("avgAgeOverMax"))
}
}
}Inheritors
Properties
Dependencies of the validation. Mapping of keys to the paths this validation depends on. Keys can be used within a ValidationContext to access the value of the dependencies.
Whether the form manager should reevaluate this validation whenever a descendant of the value being validated changes. This is false by default.
Set of external context dependencies of the validation.
Schema of the value being validated.
Value being validated.
Functions
Declares a dependency to path, accessible in the validation's context via key dependencyKey.
Declares an external context dependency to externalContextName.
Adds an observer to the path observer.toObserve to update the validation state via observer.updateState whenever an event with a path matching observer.toObserve occurs.
Adds an observer to the path pathToObserve to update the validation state via updateState whenever an event with a path matching pathToObserve occurs.
Function used to declare a dependency to a path and delegate access to its value within a ValidationContext.
Function used to declare a dependency to a path and delegate access to its value within a ValidationContext.
Destroys the validation state.
Function used to declare a dependency to an external context and delegate access to its value within a ValidationContext.
Function used to declare a dependency to an external context and delegate access to its value within a ValidationContext.
Initialises and returns the validation's state, given the value to validate within a ValidationContext containing the values of all declared dependencies.
Function used to observe the path pathToObserve and update the validation state via updateState whenever an event with a path matching pathToObserve occurs.
Runs the validation within a ValidationContext containing the value being validated and the value of all declared dependencies. Returns a flow over all found issues.
Runs the validation, given its state, within a ValidationContext containing the value being validated and the value of all declared dependencies. Returns a flow over all found issues.