Closed joerg-rade closed 1 year ago
I'm not sure I understand your question. You pass a serializer
parameter to the tabulator()
DSL builder function (in most cases it should be automatically infered because serializer()
is its default value)
I build my ColúmnDefinitions as follows:
fun buildColumns(displayCollection: CollectionDM): List<ColumnDefinition<Exposer>> {
val columns = mutableListOf<ColumnDefinition<Exposer>>()
columns.add(columnForObjectIcon(displayCollection))
columns.addAll(columnsForProperties(displayCollection))
columns.add(columnForObjectMenu())
return columns
}
Exposer allows to access values by name:
@Serializable
class Exposer(val delegate: TObject) {
var iconName = "" //required by ColumnFactory
fun dynamise(): dynamic {
val thys = this.asDynamic()
for (m in delegate.members) {
val member = m.value
if (member.memberType == MemberType.PROPERTY.type) {
val realValue = member.value
if (realValue != null) {
thys[member.id] = realValue.content
}
}
}
iconName = IconManager.find(delegate.title)
if (iconName == IconManager.DEFAULT_ICON) {
iconName = IconManager.find(delegate.domainType)
}
return thys
}
// eg. for dataNucleusId
fun get(propertyName: String): Any? {
return this.delegate.getProperty(propertyName)?.value
}
fun setIcon(icon: Icon) {
this.asDynamic()["icon"] = icon.image.src
}
}
You are using the legacy backend so I assume you are not using the latest KVision (6.x). What version is this? And how do you create your Tabulator component?
Yes - I was using legacy and KVision 5.x Trying to upgrade to ir/6.x was not successful so far - tables that used to work are broken now as well. (I'll probably stick with 5.x)
My design is centered around "dynamic" which is probably better explained in the following diagram:
Currently I think there is no way to define a serializer. Am I wrong?
It should always be possible to define a custom serializer. What's more, the serialization part is trivial, because dynamize()
is almost what you need (you just need one more JSON.stringify()
call). But the deserialization part is probably more of a challenge. Do you have any means to create an Exposer
instance out of the dynamic json data?
No - Exposer is clientside only. Changes are applied to member.values and are eventually communicated via rest calls to the server.
With KVision 5 and the legacy backend, the tabulator component can be used with three model types:
data class
, which is in general "compatible" with a JS object (has the same properties)Unfortunately your case is neither of those, that's why it's not working correctly. If creating the serializer is not possible, I think you should try to use third option - Tabulator<dynamic>
instead of Tabulator<Exposer>
. Transform your data with map
list.map {
it.dynamize()
}
and use the transformed list as tabulator input. You would have to refactor buildColumns
to use dynamic data instead of Kotlin class, but it should be possible.
Is the recommended method the same with ir/6? (I'm mostly done with the migration)
Yes, in KV 6 only option 1. and 3. are possible, so you also need to go with dynamic.
My table is still not visible. I've introduced Exhibit for serialization purposes (see https://github.com/apache/causeway/blob/kvision-6-upgrade/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/Exposer.kt)
When I debug the created tabulator I see:
and:
What am I missing?
Can I somehow run the project and see the problem on my local machine?
docker pull apache/causeway-app-demo-jpa:latest
docker run --publish 8080:8080 -ePROTOTYPING=true apache/causeway-app-demo-jpa:latest
git clone https://github.com/apache/causeway
cd causeway
git checkout kvision-6-upgrade
cd ~/incubator/clients/kroviz
gradle run
BurgerMenu -> Connect -> Url:localhost:8080/ -> OK Common Data Types -> Strings
Console should show something like:
[RT_before] tabulator(), model ->
kroviz.js:23295 ObservableListWrapper {mutableList_1: ArrayList, onUpdate_1: ArrayList}
kroviz.js:23299 Tabulator {propertyValues_1: {…}, propertyStyles_1: {…}, snStyleCache_1: null, width$delegate_1: RefreshDelegate_0, minWidth$delegate_1: RefreshDelegate_0, …}
& Thanks for looking into this!
You are not adding tabulator to your components tree. That's why it doesn't show up at all. You are creating the component with createTabulator
but you forgot to use add(...)
.
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/RoTable.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/RoTable.kt
index 52d9c5abf9..37f98a177c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/RoTable.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/RoTable.kt
@@ -76,6 +76,7 @@ class RoTable(displayCollection: CollectionDM) : SimplePanel() {
}
}
tabulator.redraw(true)
+ add(tabulator)
console.log(tabulator)
}
After fixing this I see the table on the page, but I'm not sure it looks correct. If you need more assistance please let me know.
What I have so far only partly works:
class Exposer(val delegate: TObject) {
val iconName: String = IconManager.findFor(delegate) //required by ColumnFactory
val exhibit: Exhibit
init {
val delegateUrl = getDelegateUrl()
exhibit = Exhibit(delegateUrl)
val that = exhibit.asDynamic()
that["icon"] = null
for (m in delegate.members) {
val member = m.value
if (member.memberType == MemberType.PROPERTY.type) {
val realValue = member.value
if (realValue != null) {
that[member.id] = realValue.content
}
}
}
}
}
@Serializable
class Exhibit(val url: String) {}
url is set via constructor and property names are amended via that[member.id]
- but realValue.content
doesn't break on through to the other side ;-).
Any idea what else I could try? obj {} ?
One step further ...
When using Tabulator
with a dynamic
model you need to initialize it a bit differently. Instead of passing your model as the first parameter of the constructor you need to pass it as a data
property of TabulatorOptions
. I realize it's a bit unintuitive - I've tried to hide this behind the factory functions parameters and even added a sample in the guide. But you are using the class constructor directly so nothing warns you about the problem. With this fix I can see some data in the table (dynamic data also means no need for the serializer and probably the Exibit
class can be completely removed):
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/RoTable.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/RoTable.kt
index 1658182640..762625d44a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/RoTable.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/RoTable.kt
@@ -80,8 +80,7 @@ class RoTable(displayCollection: CollectionDM) : SimplePanel() {
val className: String? = null
val init: (Tabulator<dynamic>.() -> Unit)? = null
val tableTypes = setOf(TableType.STRIPED, TableType.HOVER)
- val serializer = Exhibit::class.serializer()
- val tabulator = Tabulator(data, dataUpdateOnEdit, options, tableTypes, serializer = serializer)
+ val tabulator = Tabulator(null, dataUpdateOnEdit, options.copy(data = data.toTypedArray()), tableTypes)
if (className != null)
tabulator.addCssClass(className)
init?.invoke(tabulator)
Thanks - works now. (When I do not see the forest for the trees, I tend to take some down ... This time it looks like I threw out the baby with the water ;-)
I'm banging my head against an issue that is very similar to https://github.com/rjaros/kvision/issues/467.
The class I want to use with Tabulator (Exposer) is annotated with @Serializable. I don't see any log output in this case:
How can I pass on the serializer?![vega_in_tabulator_debug](https://user-images.githubusercontent.com/4637858/236849973-943aca4d-37d7-414f-a192-a6b5ed5d439a.png)