Forms
Introduction
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.
KVision 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 model
Form data is modeled with a standard Kotlin data class enhanced with @Serializable
annotation from kotlinx.serialization library. Every field of this model class holds the value of one input item rendered within a form. The model support most basic data types: String
, Number
(including Int
and Double
), Boolean
, Date
and also a special type List<KFile>
(a list of uploaded files).
Note: You have to add @Contextual
annotations to your Date
fields in order to explicitly allow serialization with the KVision context. You can also use @file:UseContextualSerialization(Date::class)
file annotation if you want to keep your model classes cleaner. You can find more information about this annotation in the kotlinx.serialization documentation.
Form controls
Form controls are KVision components implementing one of six FormControl
interfaces inside io.kvision.form
package: StringFormControl
, NumberFormControl
, BoolFormControl
, TriStateFormControl
, DateFormControl
and KFilesFormControl
. KVision comes with a bunch of build-in or modular form components.
Component
Interface
Module
Description
i.k.f.check.CheckBox
BoolFormControl
built-in
A check-box.
i.k.f.check.Radio
BoolFormControl
built-in
A radio-button.
i.k.f.check.RadioGroup
StringFormControl
built-in
A group of radio-buttons.
i.k.f.check.TriStateCheckBox
TriStateFormControl
built-in
A tri-state check-box.
i.k.f.text.Text
StringFormControl
built-in
A text field.
i.k.f.text.Password
StringFormControl
built-in
A text field for password input.
i.k.f.text.TextArea
StringFormControl
built-in
A text area.
i.k.f.select.Select
StringFormControl
built-in
A standard select component.
i.k.f.number.Spinner
NumberFormControl
built-in
Spinner numeric text field.
i.k.f.number.Range
NumberFormControl
built-in
A range selection field.
i.k.f.number.Numeric
NumberFormControl
built-in
A numeric form field.
i.k.f.upload.Upload
KFilesFormControl
build-in
A simple file upload component.
i.k.f.number.ImaskNumeric
NumberFormControl
kvision-imask
A numeric form field with masking.
i.k.f.time.DateTime
DateFormControl
kvision-datetime
A date and/or time selection control.
i.k.f.text.RichText
StringFormControl
kvision-richtext
A rich text editor.
i.k.f.select.TomSelect
StringFormControl
kvision-tom-select
Advanced select boxwith support for multiple selection and remote data source.
i.k.f.select.TomSelectRemote
StringFormControl
kvision-tom-select-remote
A select box for fullstack interfaces.
i.k.f.upload.BootstapUpload
KFilesFormControl
kvision-bootstrap-upload
An upload file control with preview and multi-selection.
i.k.f.text.TomTypeahead
StringFormControl
kvision-tom-select
A typeahed (autocomplete) text field with support for data source.
i.k.f.text.TomTypeaheadRemote
StringFormControl
kvision-tom-select-remote
A typeahead (autocomplete) text field for fullstack interfaces.
Note: RadioGroup
and TomSelect
controls always return String
values. Multiple selections are comma-separated.
There is also GenericRadioGroup<T>
component, which can return value of any type, but it can't be used inside Form
/FormPanel
containers.
Form containers
KVision provides a dedicated container for working with forms - FormPanel<K>
. To create a FormPanel<K>
instance you need to specify a serializer for your model data class.
You can also use a DSL builder extension function, which automatically uses default serializer for your data class.
Under the hood FormPanel
container uses non-visual form container - Form<K>
, which can be used by developers to implement their own form containers.
Data binding
You add form controls to the FormPanel
using add
method of the container, and at the same time you bind your controls to your data model by referencing class properties. The binding is type-safe, e.g. you can't bind StringFormControl
to Boolean
or Date
field.
Manual binding
If you need to manage your form directly you can create your layout using standard KVision DSL builders and bind your form controls manually using bind
extension method.
After binding your fields you can treat a FormPanel<K>
instance as a kind of a "black box" - you manage all your data flow with just a few methods - mostly setData()
and getData()
.
Form parameters
FormPanel<K>
container can layout form elements with three standard Bootstrap layouts: normal, horizontal and inline. The class constructor allows to specify other HTML form parameters as well.
Validation
KVision forms support validation for single fields and for the form as a whole. You can easily mark some fields as required, specify all needed validation functions and specify error messages, which will be displayed by the browser after validation action. Validation functions give you easy access to the values entered in the form.
Note: validatorMessage
parameters are functions with the same parameters as validator
functions.
Note: requiredMessage
and validatorMessage
parameters are optional. The default values for them are respectively "Value is required" and "Invalid value". You should use these parameters if you want to give more precise descriptions of the problems or when you want to internationalize your application.
Fieldsets
You can group several subsequent form fields within a single fieldset container by adding the same legend
parameter to the following add
method calls.
Custom field types
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 use such type with a form control based on StringFormControl
interface.
Define a custom class for your model. It needs a toString()
method to convert its data to the String
value used within a form.
Next you need to define a custom serializer for this class.
Now you can use this class within your model, by adding @Contextual
annotation.
When creating a FormPanel
container, you need to pass a reference to your serializer.
Finally you can add your data binding with a special addCustom
method.
Dynamic forms
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 KVision allows you to model your data with a Map<String, Any?>
type. To work with dynamic forms you need to create a FormPanel
container with a simplified form()
DSL builder function. Such call will return a FormPanel<Map<String, Any?>>
instance. When adding or binding form controls use string identifiers instead of property references.
Although all the fields are defined dynamically, you can still treat the form as a whole. You use getData()
and setData()
functions using standard Kotlin maps. The identifiers used for bindings will be the keys in the map.
When using dynamic forms you are intentionally loosing type safety. You need to make sure the values stored in the map are matching the types of form controls.
Last updated