Add FormFieldConverter and dataOverlayProvider to Form/FormPanel#581
Merged
rjaros merged 1 commit intorjaros:masterfrom Mar 28, 2026
Merged
Conversation
Problem:
KVision's form system only handles built-in types (String, Number, Boolean,
Date, List<KFile>) during setData/getData serialization. Custom types require
workarounds, and external components (tabulators, custom editors) have no way
to participate in form data collection without implementing FormControl.
Solution:
1. FormFieldConverter — a per-field converter interface enabling custom type
transformations between model values and form control values.
Example — storing a comma-separated list as a single Text field:
val converter = object : FormFieldConverter {
override fun fromJson(jsonValue: dynamic): Any? =
(jsonValue as? String) // model value: "a,b,c"
override fun toJson(controlValue: Any?): dynamic =
(controlValue as? String) // control value back to model
}
form.add(MyModel::tags, Text(), converter = converter)
Example — mapping an enum ordinal to a select control:
val converter = object : FormFieldConverter {
override fun fromJson(jsonValue: dynamic): Any? =
Priority.entries[jsonValue as Int].name
override fun toJson(controlValue: Any?): dynamic =
Priority.valueOf(controlValue as String).ordinal
}
form.add(MyModel::priority, TomSelect(), converter = converter)
Converters can be passed inline via the `converter` parameter on any
add()/bind() overload, or registered/removed dynamically via
registerConverter()/removeConverter().
2. dataOverlayProvider — an optional callback on Form/FormPanel that injects
external key-value pairs into getData() results, allowing non-FormControl
components to contribute form data.
Example — a tabulator contributing row data to the form:
formPanel.dataOverlayProvider = {
mapOf("rows" to tabulator.getData().serialize())
}
Overlay values bypass converter/type dispatch and validation, and take
precedence over field values on key conflicts.
Both features work in serializer and non-serializer (Map-based) form paths.
The `converter` parameter is placed before the lambda parameters
(`validatorMessage`, `validator`) to follow Kotlin's lambda-last convention.
This is fully compatible with named-argument callers. Positional callers will
see a compile error prompting them to add the new parameter.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
tfonrouge
added a commit
to tfonrouge/kvision-guide
that referenced
this pull request
Mar 26, 2026
Companion documentation for rjaros/kvision#581. Adds two new sections to the Forms page: - **Field converters**: Documents the FormFieldConverter interface as a simpler alternative to custom KSerializers for type transformations between model values and form control values. Covers inline converter via add(), registerConverter()/removeConverter(), and dynamic forms. - **Data overlay provider**: Documents the dataOverlayProvider property for injecting external component data into getData() results without implementing FormControl. Covers basic usage, precedence behavior, and validation/null/unknown-key caveats. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FormFieldConverter— per-field converter interface enabling custom type transformations between model values and form control values duringsetData()/getData(), beyond the built-in String/Number/Boolean/Date/KFiles handlingdataOverlayProvider— optional callback on Form/FormPanel that injects external key-value pairs intogetData()results, allowing non-FormControl components (tabulators, custom editors) to participate in form data collectionProblem
KVision's form system handles built-in types during serialization, but custom types require workarounds. Additionally, external components have no way to contribute data to a form without implementing
FormControl.Examples
FormFieldConverter — mapping an enum ordinal to a select control:
FormFieldConverter — via registerConverter():
dataOverlayProvider — tabulator contributing row data:
Design decisions
FormFieldConverteris a non-generic interface with two methods (fromJson/toJson) — minimal, easy to implementconverterparameter added to alladd()/bind()overloads (20+) in bothFormandFormPanel, placed before lambda parameters following Kotlin's lambda-last convention. This is fully compatible with named-argument callers; positional callers will see a compile error prompting them to add the new parameter.@Serializableclasses) and non-serializer (Map-based) form pathsremove()/removeAll()and surviveclearData()Test plan
add()add()(KProperty1 overload)registerConverter()/removeConverter()lifecycleclearData()preserves converter registrationsgetDataJson()with converter🤖 Generated with Claude Code