We need this to be able to create a Kotlin object ...
# kvision
r
We need this to be able to create a Kotlin object when using
getData()
. Without serialization requirement you would have to pass some kind of factory function. I don't know any other way to construct a generic type object.
👍 1
r
I knew there was a reason 🙂
r
If you really need
FormPanel
without serialization requirement (why?) I could add an option to pass such factory function directly to
FormPanel
. It would work fine with not serializable model class, but you would have to write a function
Map<String,Any?> -> K
by yourself for your forms.
r
I currently don't necessarily need it, I've found a workaround. Basically I have the same situation as last time, its just a MongoDB ObjectID that doesn't have a serializer. I'm not actually sure how I would write my own serializer for Bson (Binary standard object notation, mongodbs invention I think)
right now I am just converting the ObjectID into a string and passing it in to a copy class and it works fine (I thought thats how I could serialize a ObjectID)
r
Do you want to bind a data class with such a field to the FormPanel? Is it Kotlin/JS type or just some kind of wrapper for JS type?
r
yeah I want to bind it to a field in a form panel
r
KVision forms support limited set of types, which are explicitly specified (String, Boolean, Number, Date, KFile). I don't think there is a way to support user defined type even if you could write a serializer for it.
But that made me curious - perhaps it could be done with some additional generic methods
I think I made it work
You can bind a model class with a custom field type to any
StringFormControl
(e.g.
Text
) on the
FormPanel
container
You just need to: - create a custom serializer and pass it as a parameter to
FormPanel
constructor or builder - add
@ContextualSerialzation
to your field - override a
toString
method of your field class
a sample code based on showcase form example:
Copy code
// not serializable class
class ObjectId(val id: Int) {
    override fun toString(): String {
        return "$id"
    }
}

// custom serializer
object ObjectIdSerializer : KSerializer<ObjectId> {
    override val descriptor: SerialDescriptor = SerialClassDescImpl("com.example.ObjectId")

    override fun deserialize(decoder: Decoder): ObjectId {
        val str = decoder.decodeString()
        return ObjectId(str.toInt())
    }

    override fun serialize(encoder: Encoder, obj: ObjectId) {
        encoder.encodeString(obj.id.toString())
    }
}
// Form model
@Serializable
data class Form(
    val text: String? = null,
    val password: String? = null,
    val password2: String? = null,
    val textarea: String? = null,
    val richtext: String? = null,
    val date: Date? = null,
    val time: Date? = null,
    val checkbox: Boolean = false,
    val radio: Boolean = false,
    val simpleSelect: String? = null,
    val select: String? = null,
    val ajaxselect: String? = null,
    val spinner: Double? = null,
    val radiogroup: String? = null,
    val upload: List<KFile>? = null,
    @ContextualSerialization val objectId: ObjectId? = null
)

// FormPanel initialization
val formPanel = formPanel<Form>(customSerializers = mapOf(ObjectId::class to ObjectIdSerializer)) {

// Add custom field and String control to the form
addCustom(Form::objectId, Text(label = "ObjectId"))

// get form data 
formPanel.getData()
formPanel.getDataJson()

// set  form data
formPanel.setData(Form(objectId = ObjectId(14)))
😃 1
If you like this I can push this into 2.10.0
r
wow that is awesome, thanks Robert!
yeah that would be great, as long as it doesn't affect anything else!
that would clear up a lot of unecessary coding from our project! thanks again😁
158 Views