Form Validation
Form validators can be passed into the form field on creation. They can be dynamic (i.e. derived from state) to allow validation change depending on current form state or external logic.
Validators are type safe (they must be used on the correct type of field), but a string representation is also provided in the case that the raw value needs validating.
Validators are also ordered using a order field. Lower values have a higher priority.
There is no guarantee on the order 2 validators with the same order value will be called in.
Built in validators
A number of common validators are provided:
DateAfterValidatorThis checks that a date in a form box is after a specific dateDateBeforeValidatorThis checks that a date in a form box is before a specific dateDateValidatorThis checks that a date in a form box is in a valid formatEveryCharacterValidatorThis checks that every character in a text-based form box matches a conditionInvalidOptionValidatorThis checks that an item selected in a form box which has a list of discrete selectable items matches the list. For example in a dropdownMaxCountValidatorThis checks that the value in a list form box has a minimum number of items selectedMinCountValidatorThis checks that the value in a list form box has a maximum number of items selectedMaxLengthValidatorThis checks that the value in a text-based form box is not longer than a certain number of charactersMinLengthValidatorThis checks that the value in a text-based form box is not shorter than a certain number of charactersMultipleValidatorThis combines validators using a list, and is used in the backing of the+andandoperatorsMustBeTickedValidatorThis is used for a Boolean form (most commonly Checkboxes) to validate that the value istrueNotEmptyIfOtherNotPopulatedValidatorThis allows logic for at least 1 of 2 form fields to be populatedNotEmptyIfOtherPopulatedValidatorThis allows logic for 1 field with a value mandating that another field has a valueNotEmptyValidatorThis ensures a field is populatedNumberOnlyValidatorThis ensures a text field only has number charactersRegexValidatorThe ensures the value in a text field matches a regular expressionTimeAfterValidatorThis checks that a time in a form box is after a specific dateTimeBeforeValidatorThis checks that a time in a form box is before a specific dateTimeValidatorThis checks that a time in a form box is in a valid format
Most of these have a custom error message which can be provided. This can be:
StringStringResourceStringResourceWithPlaceholdersPair<StringResource, Array<String>>- Any other class implementing a custom
toStringmethod
Custom validators
The Validator interface is easy to implement for your own validation logic.
Quick inline validation can be done using the SAM constructor:
val validator = Validator<String> {value, _ ->
return if(value?.split(",")?.size == 3){
null
} else {
"4 Comma Separated Values Required."
}
}
Alternatively validation classes can be created for reuse:
class CSVValidator(
private val commaCount: Int = 3
): Validator<String> {
override fun validate(value: String?, stringRepresentation: String?): Any? {
return if(value?.split(",")?.size == commaCount){
null
} else {
"${commaCount + 1} Comma Separated Values Required."
}
}
}
The value parameter will contain the value which the form field currently holds, in a type safe way.
For example, a field which has type LocalDate will pass this value as the date in the box, if it is in a valid format (e.g. 01/01/2000)
or null otherwise (e.g. 30/30/2000 or 30/05/)
The stringRepresentation parameter will contain the raw string value of the field. This must be parsed carefully to ignore
errors if the validator wishes to use the raw format. For example, a date text field validator could
use this to ensure that the format of the date is correct before passing it down to specific value validators.
Manual Validation
Usually, the form validation will be called on submission of the form, and error messages set automatically. However, sometimes it may be preferable to validate the form box (and hence display the error) before submission has been performed.
For example, an application may wish to display validation as soon as the box is populated so the user is aware that their current input is invalid.
This can be achieved using form field value change subscription, combined with the FormBox validate function:
FormTextField(
modelProperty = FormTextFieldExampleModel::value,
validator = NumberOnlyValidator(),
updateModel = { value = it },
) {
FieldValueChangedEffect {
if(text.isNotEmpty()){
validate()
}
}
DefaultTextEntry(hint = "Value")
}
Similarly, the entire form can be validated with the validate function on the FormController