Tomasz Krakowiak
04/19/2021, 12:11 PM// Define some hooks. Maybe I'll bulk generate those for all tags later.
// Using Element API
fun CTagBuilder<OPTION>.onSelect(callback : (Event) -> Unit) {
attach<HTMLSelectElement> { element -> HTMLSelectElement
//element.onselect = callback
//or
element.addEventListener("onselect", callback)
}
}
// Using TagConsumer API
fun TagConsumer<*>.onSelect(tag : OPTION /** No multiple receivers yet : ( */, callback : (org.w3c.dom.events.Event) -> Unit) {
onTagEvent(tag, "onselect", callback)
}
// This should be global in JS / request scoped on server
val flow: Flow = Flow()
// Define mutable and observable value
val selectedStyle: Property<Style> = flow.Property(defaultStyle)
// Define some content
val styleSelectionBlock: CBlock = {
tag(::SELECT) {
for(style in availableStyles) {
tag(::OPTION) {
onSelect {
flow {
selectedStyle.value = style
}
}
}
}
}
}
fun TagConsumer<*>.styleSelectionBlock2() = {
select {
for(style in availableStyles) {
option {
onSelect(this) {
selectedStyle.value = style
}
}
}
}
}
val styleDemoBlock: CBlock = {
tag(::DIV) {
bind(DIV::classes, selectedStyle.map { setOf(it.className) })
dynamic(selectedStyle) {
"This text is shown with the style \"${it.name}\""
}
}
}
val styleSelectWithPreview : CBlock = {
styleSelectionBlock()
// styleSelectionBlock2() // That works too. kotlinx-html API is supported.
+styleDemoBlock
}
Than
// This is in commonMain, you can render to text on client too.
fun renderOnServer(out : Appendable) {
val context = RootContext(emptyMap())
context.render(styleDemoBlock, out)
}
And
val rootContext by lazy { RootContext(emptyMap())}
fun hydrateOnClient() {
// We already rendered on server. Now we're just binding model/listeners to the DOM
rootContext.hydrate(styleSelectWithPreview, rootElement)
}
// or
fun renderOnClient() {
rootContext.render(styleSelectWithPreview, rootElement)
}