https://kotlinlang.org logo
l

Lars Erik Rojeras

03/14/2022, 5:43 PM
Hi. I got a strange problem related to Tabulator 5 (I think). When I display a tabulator table using the dev server everything works as expected. But, if I build a distribution and make the files available through my own web server only the tabulator header is shown. Then I get the following error in the console:
Copy code
main.bundle.js:2 Uncaught TypeError: Cannot read properties of undefined (reading 'length')
    at sa (main.bundle.js:2:1720204)
    at new ii (main.bundle.js:2:2579880)
    at hx (main.bundle.js:2:2370990)
    at Rx.toKotlinObj_t5tk2r$ (main.bundle.js:2:2399627)
    at tn.toKotlinObjTabulator_e9s2f4$ (main.bundle.js:2:2554636)
    at tn.fixData_giv383$ (main.bundle.js:2:2554164)
    at Fe.<anonymous> (main.bundle.js:2:2543681)
    at main.bundle.js:2:1366879
    at Array.forEach (<anonymous>)
    at Te._dispatch (main.bundle.js:2:1366854)
sa @ main.bundle.js:2
ii @ main.bundle.js:2
hx @ main.bundle.js:2
Rx.toKotlinObj_t5tk2r$ @ main.bundle.js:2
tn.toKotlinObjTabulator_e9s2f4$ @ main.bundle.js:2
tn.fixData_giv383$ @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
_dispatch @ main.bundle.js:2
dispatchExternal @ main.bundle.js:2
load @ main.bundle.js:2
_loadInitialData @ main.bundle.js:2
_create @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
setTimeout (async)
Re @ main.bundle.js:2
Fe @ main.bundle.js:2
hx @ main.bundle.js:2
tn.createJsTabulator @ main.bundle.js:2
tn.afterInsert_77isfd$ @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
Le.patch_6ju63b$ @ main.bundle.js:2
Tw.reRender_8be2vx$ @ main.bundle.js:2
Tw.singleRender_klfg04$ @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
setTimeout (async)
Tw.singleRenderAsync_o14v8n$ @ main.bundle.js:2
kp.singleRenderAsync_o14v8n$ @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
g.dispatch_dtrwrh$ @ main.bundle.js:2
an.domdbLoadingComplete @ main.bundle.js:2
Gn @ main.bundle.js:2
o.onload @ main.bundle.js:2
load (async)
en @ main.bundle.js:2
Kn @ main.bundle.js:2
an.initialize @ main.bundle.js:2
Kt.start @ main.bundle.js:2
Te.start_x7u0o8$ @ main.bundle.js:2
a @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
main.bundle.js:2 redraw failed - table not yet initialized. Please wait for the `tableBuilt` event before calling this function.
redraw @ main.bundle.js:2
(anonymous) @ main.bundle.js:2

redraw failed - table not yet initialized. Please wait for the `tableBuilt` event before calling this function.
redraw @ main.bundle.js:2
(anonymous) @ main.bundle.js:2
I guess it can be related to https://github.com/olifolkerd/tabulator/issues/3407, but I do not use setData() in my code. Still using the legacy compiler. Any ideas?
r

Robert Jaros

03/14/2022, 5:55 PM
Do you use the current KVision version?
l

Lars Erik Rojeras

03/14/2022, 7:08 PM
I upgraded to 5.8.2 and I still see the error. Will check more tomorrow.
r

Robert Jaros

03/15/2022, 5:24 AM
From your stacktrace I assume your tabulator is using some fallback, legacy-only KVision code to automatically convert javascript data to kotlin objects by copying properties. It was designed only for simple data classes and is generally not recommended anymore, since it's way stable to use serialization. Just make your data model
@Serializable
and pass a
KSerializer<T>
to your Tabulator constructor/builder.
l

Lars Erik Rojeras

03/15/2022, 7:13 AM
My data model in Tabulator is a
Copy code
val DomainArr = mutableListOf<ServiceDomain>()
and ServiceDomain:
Copy code
@Serializable
data class ServiceDomain(
    val name: String,
    val description: String = "",
    val swedishLong: String = "",
    val swedishShort: String = "",
    val owner: String? = null,
    val hidden: Boolean,
    val domainType: DomainType,
    val issueTrackerUrl: String? = null,
    val sourceCodeUrl: String? = null,
    val infoPageUrl: String? = null,
    val interactions: Array<Interaction>? = null, //  = arrayOf<Interaction>(),
    val serviceContracts: List<Contract>? = null, //  = listOf<Contract>(),
    val versions: Array<Version>? = null,
) {
    var domainTypeString: String? = null // Used for filtering in tabulator

    /**
     * The init block verifies and store the accepted domains.
     */
    init {
        if (
            interactions != null &&
            serviceContracts != null &&
            versions != null
        ) {
            DomainMap[this.name] = this
            DomainArr.add(this)
            domainTypeString = domainType.name
        } else {
            if (!this.name.isBlank()) println("${this.name} is incomplete and removed")
        }
    }
}
It is populated through:
Copy code
val domDb: DomDb = json.decodeFromString(DomDb.serializer(), response)
(where the DomDb class contains a list of <ServiceDomain>. Are there something in this that might cause the problem?
r

Robert Jaros

03/15/2022, 9:26 AM
Everything other than simple
val
primitive can cause problems. But as your data model is
@erializable
, just pass the
ServiceDomain.serializer()
to your tabulator component and it should work fine.
serializer = serializer()
should work
the correct type will be inferred automatically
l

Lars Erik Rojeras

03/15/2022, 9:53 AM
Thank you Robert, you are right as always! 🙂 It works when I add the serializer parameter to Tabulator.
r

Robert Jaros

03/15/2022, 10:16 AM
what's more, it will also work fine with IR
2 Views