Using chart js

Hi, how can I use chartjs in our kotlin/js project?

I’ve tried adding dependencies in my build.gradle.kts. But there’s still no Chart object to be imported in my kotlin files.

repositories {
mavenCentral()
jcenter()
}

dependencies {
implementation(“org.jetbrains.kotlin:kotlin-stdlib-js”)
implementation(“org.jetbrains.kotlin:kotlin-stdlib:1.3.72”) // or “kotlin-stdlib-jdk8”

implementation(npm("chart.js"))

}

kotlin {
target {
// You can drop browser or node if you targeting only one
browser()
// nodejs()
}
sourceSets[“main”].dependencies {
implementation(npm(“chart.js”))
}
}

Hi,
what you wrote as gradle build is just the first step.
In order to import external javascript modules you need to recreate their declaration, something similar to typescript definitions (*.d.ts) but for Kotlin JS.
There is a tool called dukat => https://github.com/Kotlin/dukat , I found it very helpful to understand how to create those “definition” files in Kotlin.
I can show you a little example of what I did discover when I was trying to import apollo-server module, I guess it can be used for chart js too.

Consider an example like:

const {ApolloServer} = require('apollo-server')

const apollo = new ApolloServer("a configuration")

apollo.listen(...).then(...)

In order to make this possible in Kotlin Js you need to describe apollo-server module, the one you are importing.
A possible approach would be creating a Kotlin file that contains something like:

// here you specify the name of the javascript module you want to describe
@file:JsModule("apollo-server")
@file:JsNonModule
package com.package

import kotlin.js.Promise

// here you specify how the module should be
// defining it as external

external interface ServerInfo {
    var address: String
    var family: String
    var url: String
    var subscriptionsUrl: String
    var port: dynamic /* Number | String */
        get() = definedExternally
        set(value) = definedExternally
    var subscriptionsPath: String
    var server: Any
}

external open class ApolloServer(config: Any? /* ApolloServerExpressConfig & `T$0` */) : Any {
    open var httpServer: Any
    open var cors: Any
    open var onHealthCheck: Any
    open var createServerInfo: Any
    open fun applyMiddleware()
    open fun listen(vararg opts: Any): Promise<ServerInfo>
    open fun stop(): Promise<Unit>
}

everywhere else you can use ApolloServer class directly like:

    ApolloServer(null).listen().then {
       ...
    }

That bit above is transpiled for you in something like:

  function main$lambda(it) {
    //  ...
    return Unit;
  }
  function main() {
    (new ApolloServer(null)).listen().then(main$lambda);
  }

You might need to do the same with chart js, check what dukat is exporting and reuse part of it, at least the minimum part to make it work.

Thank you for the detail explanation. Actually I have tried dukat. I’ve install dukat from npm. And download the typescript definition from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/chart.js/index.d.ts

But the generated file is not recognized by kotlin. I guess there are still a few manual things need to be done. I’m going to try it again following your explanation. Thanks

As you pointed at, I would use dukat (currently at 0.28) just to have an idea of how the main module (main declarations) of your dependency should look like and reuse part of what it generates. You don’t really need to map everything as dukat does, only the calls/objects you are using. As far as I got… this process is, unfortunately, very manual, at least in modules like apollo-server that is spreaded in a lot of other modules.
Sooner or later, I expect, people will start to create Kotlin JS modules definitions like @DefinitelyTyped in Typescript.

You can copy compilable Kotlin definitions, which I’ve created with the help of an old ts2kt tool for my KVision framework (https://github.com/rjaros/kvision/blob/master/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/js/Chart.kt). The sources are published with MIT licence.

Of course you can also use KVision to easily create charts based on chart.js :slight_smile:

Yes. I would probably go that way. Just building the things that I need. Thanks

Thanks. I will look into it.