diff options
3 files changed, 67 insertions, 32 deletions
diff --git a/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt index bdae5091..e1678e90 100644 --- a/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt +++ b/kvision-modules/kvision-bootstrap-upload/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt @@ -61,7 +61,7 @@ suspend fun <K : Any> Form<K>.getDataWithFileContent(): K { value.getValue() } }) - return this.modelFactory(map.withDefault { null }) + return this.modelFactory?.invoke(map.withDefault { null }) ?: throw IllegalStateException("Serializer not defined") } /** diff --git a/src/main/kotlin/pl/treksoft/kvision/form/Form.kt b/src/main/kotlin/pl/treksoft/kvision/form/Form.kt index 783653ce..eb0e5aee 100644 --- a/src/main/kotlin/pl/treksoft/kvision/form/Form.kt +++ b/src/main/kotlin/pl/treksoft/kvision/form/Form.kt @@ -55,42 +55,45 @@ internal data class FieldParams<in F : FormControl>( * @param K model class type * @param panel optional instance of [FormPanel] * @param serializer a serializer for model type + * @param customSerializers a map of custom serializers for model type */ @Suppress("TooManyFunctions") class Form<K : Any>( private val panel: FormPanel<K>? = null, - private val serializer: KSerializer<K>, + private val serializer: KSerializer<K>? = null, private val customSerializers: Map<KClass<*>, KSerializer<*>>? = null ) { - val modelFactory: (Map<String, Any?>) -> K + val modelFactory: ((Map<String, Any?>) -> K)? val fields: MutableMap<String, FormControl> = mutableMapOf() internal val fieldsParams: MutableMap<String, Any> = mutableMapOf() internal var validatorMessage: ((Form<K>) -> String?)? = null internal var validator: ((Form<K>) -> Boolean?)? = null init { - modelFactory = { - val json = js("{}") - it.forEach { (key, value) -> - val v = when (value) { - is Date -> { - value.toStringF() - } - is List<*> -> { - @Suppress("UNCHECKED_CAST") - ((value as? List<KFile>)?.toObj(KFile.serializer().list)) + modelFactory = serializer?.let { + { + val json = js("{}") + it.forEach { (key, value) -> + val v = when (value) { + is Date -> { + value.toStringF() + } + is List<*> -> { + @Suppress("UNCHECKED_CAST") + ((value as? List<KFile>)?.toObj(KFile.serializer().list)) + } + else -> value } - else -> value + json[key] = v } - json[key] = v - } - val serializersModule = if (customSerializers == null) { - serializersModuleOf(Date::class, DateSerializer) - } else { - serializersModuleOf(customSerializers + (Date::class to DateSerializer)) + val serializersModule = if (customSerializers == null) { + serializersModuleOf(Date::class, DateSerializer) + } else { + serializersModuleOf(customSerializers + (Date::class to DateSerializer)) + } + DynamicObjectParser(serializersModule).parse(json, serializer) } - DynamicObjectParser(serializersModule).parse(json, serializer) } } @@ -274,7 +277,7 @@ class Form<K : Any>( */ fun getData(): K { val map = fields.entries.associateBy({ it.key }, { it.value.getValue() }) - return modelFactory(map.withDefault { null }) + return modelFactory?.invoke(map.withDefault { null }) ?: throw IllegalStateException("Serializer not defined") } /** @@ -282,17 +285,21 @@ class Form<K : Any>( * @return data model as JSON */ fun getDataJson(): Json { - val serializersModule = if (customSerializers == null) { - serializersModuleOf(Date::class, DateSerializer) + return if (serializer != null) { + val serializersModule = if (customSerializers == null) { + serializersModuleOf(Date::class, DateSerializer) + } else { + serializersModuleOf(customSerializers + (Date::class to DateSerializer)) + } + NativeJSON.parse( + kotlinx.serialization.json.Json(context = serializersModule).stringify( + serializer, + getData() + ) + ) } else { - serializersModuleOf(customSerializers + (Date::class to DateSerializer)) + NativeJSON.parse("{}") } - return NativeJSON.parse( - kotlinx.serialization.json.Json(context = serializersModule).stringify( - serializer, - getData() - ) - ) } /** diff --git a/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt b/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt index 7353179a..35d64751 100644 --- a/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt +++ b/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt @@ -102,13 +102,14 @@ enum class FormTarget(internal val target: String) { * @param horizRatio horizontal form layout ratio * @param classes set of CSS class names * @param serializer a serializer for model type + * @param customSerializers a map of custom serializers for model type */ @Suppress("TooManyFunctions") open class FormPanel<K : Any>( method: FormMethod? = null, action: String? = null, enctype: FormEnctype? = null, private val type: FormType? = null, condensed: Boolean = false, horizRatio: FormHorizontalRatio = FormHorizontalRatio.RATIO_2, classes: Set<String> = setOf(), - serializer: KSerializer<K>, customSerializers: Map<KClass<*>, KSerializer<*>>? = null + serializer: KSerializer<K>? = null, customSerializers: Map<KClass<*>, KSerializer<*>>? = null ) : SimplePanel(classes) { /** @@ -516,3 +517,30 @@ inline fun <reified K : Any> Container.formPanel( this.add(formPanel) return formPanel } + +/** + * DSL builder extension function. + * + * Simplified version of formPanel container without data model support. + */ +fun Container.form( + method: FormMethod? = null, action: String? = null, enctype: FormEnctype? = null, + type: FormType? = null, condensed: Boolean = false, + horizRatio: FormHorizontalRatio = FormHorizontalRatio.RATIO_2, + classes: Set<String>? = null, className: String? = null, + init: (FormPanel<Any>.() -> Unit)? = null +): FormPanel<Any> { + val formPanel = + FormPanel<Any>( + method, + action, + enctype, + type, + condensed, + horizRatio, + classes ?: className.set + ) + init?.invoke(formPanel) + this.add(formPanel) + return formPanel +} |