rjaros / kvision

Object oriented web framework for Kotlin/JS
https://kvision.io
MIT License
1.24k stars 67 forks source link

Allow to use custom format for DateFormControl on Form.setData() #552

Closed tfonrouge closed 2 days ago

tfonrouge commented 3 days ago

Hello,

Currently on Forms, the DateFormControl relies on String.toDateF() to assign the control's value, but the function toDateF() uses the const KV_DEFAULT_DATE_FORMAT whos value is hard coded to "YYYY-MM-DD HH:mm:ss" :

fun String.toDateF(format: String = KV_DEFAULT_DATE_FORMAT): Date
const val KV_DEFAULT_DATE_FORMAT = "YYYY-MM-DD HH:mm:ss"

In my fullstack projects, for date types, I use ISO DATETIME serialization format which is more portable, keeps info about UTC and is friendly with MongoDb date format.

I see that KVision uses the https://github.com/taylorhakes/fecha#formatting-tokens for the moment.js library and it supports ISO DATETIME format with "isoDateTime" value. In order to standarize my projects I've builded a KVision SNAPSHOT version with a mutable KV_DEFAULT_DATE_FORMAT var:

var KV_DEFAULT_DATE_FORMAT = "YYYY-MM-DD HH:mm:ss"

So I can set the format widely to KVision date controls just with:

KV_DEFAULT_DATE_FORMAT = "isoDateTime"

And this works like a charm with KVision datetime controls and also with native Tabulator.info Formatter.DATETIME and Editor.DATETIME built in methods on column definitions with the Luxon library.

The KV_DEFAULT_DATE_FORMAT const can be changed to a mutable var or is there any other way to achieve this ?

thanks for any insight

rjaros commented 3 days ago

Hello. I wonder, isn't this the internal representation of form data model? When using forms with getData() or setData() you work with Date types. I think this internal format is only visible when using getDataJson() method? Is this the method you are using?

tfonrouge commented 3 days ago

Hi

No, I only use getData()/setData() to get/set that data model in the forms, however I have a custom serializer in the backend for the OffsetDateTime type which sends to the frontend the dateTime serialized in a ISO 8601 format. In the KVision datetime controls the setDate() uses toDateF() with a format "YYYY-MM-DD HH:mm:ss" which is not able to read de data for the control because the data is in ISO 8601 string format

Also, the Tabulator.info ColumnDefinition formatter and editor for datetime, seems to update the internal data model representation for the updated row (a pure json object) in the ISO 8601 format when using the "iso" modifier in their configuration.

tfonrouge commented 3 days ago

Hello,

I've created a small example which will show what the problem is: https://github.com/tfonrouge/datetest The example is a very simple fullstack app where the backend provide a Person(name, birthday) database, the frontend screen will show you with a tabulator with the Person items and an FormPanel on the top that shows the values of the any selected Person row.

The Person.Birthday field type is OffsetDateTime, and the required Serializer is also provided.

Screenshot_20241126_215407

The green arrow shows the Birthday field but the value is incorrect because the DateFormControl is trying to decode the datetime value (in ISO 8601 serialized string format) with an incorrect mask.

The Birthday cell accepts edit and it updates the Birthday value back to the backend database.

In order to make the DateFormControl to read the value , is required to have the _KV_DEFAULT_DATEFORMAT as a mutable var to assign a different format, in this case "isoDateTime" in the App.kt file:

Screenshot_20241126_220209

I need to keep the OffsetDateTime Serialization with ISO 8601 format, but of course also is possible that I've missed something that solves this in another simpler way, so please advice.

ty

rjaros commented 3 days ago

Hello,

I understand your issue. You are using @Serializable(with = OffsetDateTimeSerializer::class) inside your Person class, while KVision is designed to use @Contextual serialization on date fields. This makes your class incompatible with the framework, because it uses it's own serializers, expects the model classes to use them and assumes the date fields are serialized using standard format.

Changing KV_DEFAULT_DATE_FORMAT is a bit like cheating :-), because this constant is used by these internal serializers.

If I were to suggest a solution compatible with KVision design, I would use @Contextual on the model class and keep the KVision side clean (without any non-standard changes). On the backend side, you can probably specify your own serializer for contextual fields with type OffsetDateTime when accessing MongoDb.

But as pragmatic person, I also don't really see the problem with modifying KV_DEFAULT_DATE_FORMAT to be a variable. It shouldn't break anything and sometimes could be helpful. If you want this change, just make a PR.

tfonrouge commented 2 days ago

Hello,

Thank you Robert, I agree with you in having clean the framework and in fact I see that KVision is very clean and at the same time flexible, also I think that having the chance to customize the value of KV_DEFAULT_DATE_FORMAT also gives flexibility due to the fact that precisely it involves the serialization of date types.

I'll make the PR and thank you again.