https://kotlinlang.org logo
#javascript
Title
# javascript
a

Arjan van Wieringen

12/01/2023, 11:00 AM
Has anyone had any success with making web-components via Kotlin/JS? I've stumbled upon the following sources: https://discuss.kotlinlang.org/t/creating-a-custom-element-webcomponent/3988/14 https://github.com/semantic-logic-tools/kotlin-web-component But so far, to no avail. Every code I tried I get stranger and stranger errors. Does anyone have any working examples?
a

Artem Kobzar

12/01/2023, 12:12 PM
We had a prototype inside team with the
lit
library. I will try to open-source it until the end of this year.
t

turansky

12/01/2023, 12:49 PM
We have fixed
HTMLElement
in Kotlin Wrappers with 0 abstract methods. Single known problem - registration in
customElementRegistry
, which is sideeffect, which must be applied, only if component used.
a

Arjan van Wieringen

12/01/2023, 1:39 PM
@turansky thanks, these Kotlin wrappers are additional to the Kotlin Js browser api right? The problem you mention with the registry, how is this an issue? I can apply it like any normal function right?
t

turansky

12/01/2023, 1:42 PM
Kotlin wrappers are additional to the Kotlin Js browser api right?
It's full replacemant. To avoid redundant imports you can use this flag.
I can apply it like any normal function right?
You can call registration in
main
function. As result - tree shaking won't work
👍 1
👍🏾 1
a

Arjan van Wieringen

12/01/2023, 2:13 PM
Hmm, I am getting errors:
Copy code
@JsExport
class HelloWorldElement : HTMLElement() {
    init {
        innerHTML = "Hello World"
    }
}

fun main() {
    window.customElements.define("hello-world", { HelloWorldElement() })
}
And the error is:
Copy code
Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
t

turansky

12/01/2023, 2:14 PM
a

Arjan van Wieringen

12/01/2023, 2:15 PM
Ah yes, I only had esModules enabled...
Too bad. First of all it completely breaks when I have compose plugin enabled, after disabling that one I get:
Copy code
Uncaught TypeError: Illegal constructor
    at createExternalThis (coreRuntime.kt:242:24)
    at HelloWorldElement.new_nl_avwie_webcomponent_HelloWorldElement_vllg41_k$ (compose-web-component.js:15:19)
    at new main$lambda (App.kt:14:51)
createExternalThis @ coreRuntime.kt:242
new_nl_avwie_webcomponent_HelloWorldElement_vllg41_k$ @ compose-web-component.js:15
main$lambda @ App.kt:14
I was hoping to have a Compose HTML working behind a shadow-dom, but I think that will be quite difficult.
t

turansky

12/01/2023, 2:19 PM
What if you will replace
init
with constructor body?
a

Arjan van Wieringen

12/01/2023, 2:23 PM
No, nothing changes. Even if I remove the init and don't do any constructor actions at all
Thanks for you help by the way. I really appreciate it 🙂
t

turansky

12/01/2023, 2:24 PM
I see
You have invalid registration
Expected:
Copy code
customElements.define("hello-world", HelloWorldElement::class.js)
a

Arjan van Wieringen

12/01/2023, 2:26 PM
That doesn't work, it should be
Copy code
class HelloWorldElement : HTMLElement() {
}

fun main() {
    window.customElements.define("hello-world", { HelloWorldElement::class.js })
}
However, then i get
Copy code
Uncaught TypeError: Failed to construct 'CustomElement': The result must implement HTMLElement interface
😄
t

turansky

12/01/2023, 2:27 PM
It's not what I wrote
Don't add lambda please
Please use Kotlin Wrappers with strict signatures
a

Arjan van Wieringen

12/01/2023, 2:29 PM
There are differences between the kotlin-wrapper
customElements
and the normal one. However, this wont work:
Copy code
```import web.html.HTMLElement
import web.html.customElements


class HelloWorldElement : HTMLElement() {
}

fun main() {
    customElements.define("hello-world", HelloWorldElement::class.js)
}
Which results in a compiler error:
Copy code
Type mismatch.
Required:
CustomElementConstructor /* = JsClass<HTMLElement> */
Found:
JsClass<HelloWorldElement>
t

turansky

12/01/2023, 2:29 PM
In
kotlin-browser
you will find strict declarations for
CustomElementRegistry
Just for test
Copy code
customElements.define("hello-world", HelloWorldElement::class.js.asDynamic())
a

Arjan van Wieringen

12/01/2023, 2:33 PM
It doesn't crash anymore, so that's positive.
However, nothing happens. The
connectedCallback
etc handlers are missing from the wrappers. Am I correct?
Works:
Copy code
@JsExport
class HelloWorldElement : HTMLElement() {

    @JsName("connectedCallback")
    fun connectedCallback() {
        innerHTML = "<h1>Hello World</h1>"
    }
}

fun main() {
    customElements.define("hello-world", HelloWorldElement::class.js.asDynamic())
}
Coolio
t

turansky

12/01/2023, 2:37 PM
a

Arjan van Wieringen

12/01/2023, 2:37 PM
Wow, that's fast
Too bad Compose Compiler doesn't work with ES classes... yet
t

turansky

12/01/2023, 2:41 PM
However, nothing happens. The
connectedCallback
etc handlers are missing from the wrappers. Am I correct?
In TypeScrript it's also isn't declared 🙂
a

Arjan van Wieringen

12/01/2023, 2:41 PM
Makes sense. 'Magic' methods 😉
t

turansky

12/01/2023, 2:43 PM
Draft - declare it as optional property 😞
More elegant - additional interfaces
a

Arjan van Wieringen

12/01/2023, 2:44 PM
Yeah. Well at least I am happy I got something on my screen. Working around the interfaces isn't a problem. But Compose compiler is blocking for me now sadly. https://youtrack.jetbrains.com/issue/KT-63991/Jetbrains-Compose-compiler-failes-on-web-project-with-useEsClasses-or-useEsModules-enabled
t

turansky

12/01/2023, 2:44 PM
Like
HasConnectedCallback
a

Arjan van Wieringen

12/01/2023, 2:44 PM
Thanks a lot for your help. Mainly they were config issues on my side.
😉 1
t

turansky

12/02/2023, 2:09 PM
Wrappers
pre.654
release.
asDynamic()
call can be removed.
3 Views