Forms
Last updated
Last updated
Forms are one of the most important parts of GUI of many applications, especially the ones which collect and manage data from the users. Traditionally handling HTML forms is a complex process, composed of many small steps like placing HTML form controls on the page, setting and displaying initial data, reading user data from individual HTML elements and finally transforming and validating the data. It gets even worse if you are using custom visual components for complex data types - date, time, rich text, multiple select, uploaded files etc.
Kilua lets you work with forms in a very simple, consistent and efficient way. It hides all complex data transformations inside the framework logic and offers you a fully type-safe binding between your data and your forms. It has support for many different, both simple and complex, form controls. And it gives you ready to use data validation.
Form data is modelled with a standard Kotlin data class enhanced with @Serializable
annotation from library. Every field of this model class holds the value of one input item rendered within a form. The model support basic data types: String
, Number
(including Int
and Double
), Boolean
, LocalDate
, LocalTime
, LocalDateTime
and also a special type List<KFile>
(a list of uploaded files).
Kilua comes with a bunch of built-in or modular form composables for many different types of form data:
text()
String?
built-in
A text field
textArea()
String?
built-in
A text area
password()
String?
built-in
A password field
checkBox()
Boolean
built-in
A checkbox
triStateCheckBox()
Boolean?
built-in
A tri-state checkbox (with null
state)
radio()
Boolean
built-in
A radio button
radioGroup()
String?
built-in
A group of radio buttons
colorPicker()
String?
built-in
An HTML color picker
numeric()
Number?
built-in
A numeric field
range()
Number?
built-in
A range field
spinner()
Int?
built-in
A spinner numeric field
select()
String?
built-in
A simple select field
date()
LocalDate?
built-in
A simple HTML date picker
dateTime()
LocalDateTime?
built-in
A simple HTML date and time picker
time()
LocalTime?
built-in
A simple HTML time picker
upload()
List<KFile>?
built-in
A File picker
imaskNumeric()
Number?
kilua-imask
A numeric field with masking
richText()
String?
kilua-trix
A rich text editor
richDate()
LocalDate?
kilua-tempus-dominus
A rich date picker
richDateTime()
LocalDateTime?
kilua-tempus-dominus
A rich date and time picker
richTime()
LocalTime?
kilua-tempus-dominus
A rich time picker
tomSelect()
String?
kilua-tom-select
A rich select field
tomTypeahead()
String?
kilua-tom-select
A text field with autocomplete
To create a form just use a form
composable function, using a type parameter for static data model.
Let's build an example login form, with two standard fields and additional "remember me" checkbox. We will use this data model class:
We start with a form
composable:
Next, we need to add form controls:
We connect form controls with our data model using bind
method calls:
Now our form (strictly speaking a component created by the composable, which can be accessed with this@form
or returned with formRef {}
variant of the composable) can be treated as a kind of "black box". We can both get and set the data using our model class with getData()
and setData()
methods. In our case we can initialize the form with some non-default values (rememberMe = true
) and print login data after clicking the "Login" button:
Our form is working, but it's not very accessible, because there are no labels for our fields. We can add them manually:
We can also use a fieldWithLabel
helper function, which will automatically generate ID attributes for our controls:
And finally we can add some flexbox styling to make the form more visually appealing:
Kilua forms support validation for single fields and for the form as a whole. You can easily mark some fields as required using required = true
parameter. You can specify validation functions and error messages for single fields using bindWithValidationMessage
method instead of simple bind
. You can also set validator
function for the whole form and check the relationships between different fields. Finally you can validate the form with the validate()
method:
The results of the validation process are not displayed automatically. Instead they are collected in the Validation
object, which can be accessed with validationStateFlow
property of the form component. You can use validationStateFlow.collectAsState()
to handle validation as standard compose state. It's up to you how to display the collected validation data. This is only an example:
Form data model doesn't support custom types out of the box, but it's possible to add support for your own type as long as you can convert this type to and from a String
.
Define a custom class for your model. It needs a toString()
method to convert its data to the String
value used within a form and should be serializable with a custom serializer.
Now you can use this class within your data model.
When creating a form, you can use any control based on String
data type and use bindCustom
method to create data binding.
Sometimes it's not possible to know the data model of the form because the fields need to be added and/or removed dynamically. For such use cases Kilua allows you to model your data with a Map<String, Any?>
type. The values are still strictly typed, but you need to use casting to access the correct type of data. To create a dynamic form just use form
composable without any type parameter and create bindings using plain string identifiers: