Hi, I couldn't figure out, how to bind the DateTi...
# kvision
k
Hi, I couldn't figure out, how to bind the DateTime component to a common Model's field with the type (ZonedDateTime/LocalDateTime/Long) in commonMain in my full-stack app. I can see examples with frontend bound to kotlin.js.Date type Do I need to add the dependency of kotlin.stdlib-js in the common and backend to bind this and then convert it before storing it in the database? Or is there a way in the frontend layer to convert the value to a Long?
r
You need to use KVision's common types in your model, e.g.
io.kvision.types.LocalDateTime
it will be mapped to
kotlin.js.Date
on the frontend side
and to
java.time.LocalDateTime
on the backend
you can use any of them with
DateTime
component because all of them will be mapped as
kotlin.js.Date
you can of course create your own types and map them as well, but KVision interfaces support only those five (with built-in custom serializers/deserializers)
for any other types you will need to implement your own serializers
k
Thank you for the reply... I tried this.. In the common model:
Copy code
val myAttribute: LocalDateTime? = null,
in the frontend in the Panel...
Copy code
add(
    MyObject::myAttribute,
    DateTime(format = "DD-MM-YYYY", label = "label..")
)
When I tried to print for debugging it throws ClassCastException in the console.
Copy code
console.log("date value: ${formData.myAttribute}")
I must be doing something wrong then...
formData being the variable assigned after the validate() on the panel..
Copy code
val formData = myPanel.getData()
r
I'll check this out
k
cheers
r
seems to be working for me
in common I have:
Copy code
@file:UseContextualSerialization(LocalDateTime::class)

package com.example

import io.kvision.types.LocalDateTime
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseContextualSerialization

@Serializable
data class FormData(val myAttribute: LocalDateTime? = null)
and on the frontend side:
Copy code
val fp = formPanel<FormData> {
                add(FormData::myAttribute, DateTime(format = "DD-MM-YYYY", label = "test"))
            }
            button("test").onClick {
                console.log(fp.getData().myAttribute?.toStringF("DD-MM-YYYY"))
            }
k
Interesting, I have the same code.. I will try to reproduce it in the test repo..
r
legacy or IR?
i'm testing IR
k
legacy one
r
I'll try legacy then
k
great!
r
working fine with legacy as well
please try to reproduce and let me know or fill an issue
k
sure will do..
It works in the test repo.. So it must be something wrong with the field mapping in the model.. Cheers
got it working.. Another quick question on the dates. Usually, I use ZonedDateTime and store the epochMillis in the database with the UTC as the default timezone. Question1: Any plan to support ZonedDatetime in kvision?
Quesiton2: Will the bound OffsetDateTime always gets the browser's Locale specific timezone?
r
why can't you use OffsetDateTime?
I don't really feel the difference between the two, but here it is said, the OffsetDateTime should be used to store date in db: https://www.baeldung.com/java-zoneddatetime-offsetdatetime
As for q2 - I'm not really sure 🙂 I've been trying to implement rational mappings between different jvm java.time.* types and single js Date type. But I'm not sure it will work with all use cases. You need to test this.
The java.time.* objects are always serialized as strings and recreated to js.Date with this code: https://github.com/rjaros/kvision/blob/master/kvision-modules/kvision-common-remote/src/jsMain/kotlin/io/kvision/types/Date.kt#L51
as you can see it's quite complicated 🙂
k
Cool.. 1. I will use the OffsetDateTime then.. 2. I will test with various browser locale setting and then get back..
using OffsetDateTime / LocalDateTime type in the common model with @Serializable for storing in Google Firestore, I get this error:
Copy code
2021-05-21 21:12:10,113 [Gax-3] ERROR io.kvision.remote.KVServiceManager - Could not deserialize object. Class java.time.LocalDateTime does not define a no-argument constructor. 
If you are using ProGuard, make sure these constructors are not stripped (found in field 'myField')
java.lang.RuntimeException: Could not deserialize object. Class java.time.LocalDateTime does not define a no-argument constructor. 
If you are using ProGuard, make sure these constructors are not stripped (found in field 'myField')
        at com.google.cloud.firestore.CustomClassMapper.deserializeError(CustomClassMapper.java:614)
        ....
it actually stores that field, as an object in Firestore.. like dayOfMonth, dayOfWeek, ... offsert, rules..etc, so while fetching it cannot deserialize
r
And do I understand correctly - it works with ZonedDateTime?
But ZonedDateTime doesn't have no-arg constructor as well ...
k
ZonedDateTime doesn't work too.. W
The offsetDateTime is peristed in Firestore as an object with nested properties, but while retreiving the deserializer cannot find the shape in the Model. I just did a workaround: Added a transient field and bound the value from the form, and store the epoch in another field and stored it, it works that way..
r
Never used Firestore, so I can't help.
But for the sake of completeness I have implemented ZonedDateTime support in KVision interfaces.
k
Wow, thats great.. I will upgrade and see if that works..