Blog

kweb で再利用可能なコンポーネントを使いたいばあいは kweb.state.Component を実装する

https://docs.kweb.io/book/components.html

kweb でサイトを作っている場合、複数画面で再利用可能なパーツが出来上がる時がある。そういう場合は、kweb.state.Component を継承させれば良い。

このブログで使っている編集フォームはエントリー作成画面とほぼ同一なので共通化してみたので以下のようになった。

package blog3.admin.form

import kweb.ButtonType
import kweb.Element
import kweb.ElementCreator
import kweb.button
import kweb.div
import kweb.form
import kweb.input
import kweb.option
import kweb.plugins.fomanticUI.fomantic
import kweb.select
import kweb.state.Component
import kweb.state.KVar
import kweb.textArea
import kweb.util.json

class EntryForm(
    private val initialTitle: String? = null,
    private val initialBody: String? = null,
    private val initialStatus: String = "draft",
    private val onSubmit: (title: String, body: String, status: String) -> Unit,
) : Component {
    override fun render(elementCreator: ElementCreator<Element>) {
        with(elementCreator) {
            lateinit var titleVar: KVar<String>
            lateinit var bodyVar: KVar<String>
            lateinit var statusVar: KVar<String>

            val form = form(fomantic.ui.form) {
                div(fomantic.field) {
                    titleVar = input(
                        initialValue = initialTitle,
                        name = "title",
                        attributes = mapOf("required" to true.json)
                    ).value
                }
                div(fomantic.field) {
                    val textArea = textArea(required = true, cols = 80, rows = 20)
                    textArea.text(initialBody.orEmpty())
                    bodyVar = textArea.value
                }
                div(fomantic.field) {
                    statusVar = select(required = true) {
                        listOf("draft", "published").forEach { status ->
                            option(mapOf("value" to status.json)) {
                                it.text(status)
                                if (initialStatus == status) {
                                    it.setAttributes("selected" to "selected".json)
                                }
                            }
                        }
                    }.value
                    statusVar.value = initialStatus
                }
                div(fomantic.field) {
                    button(fomantic.button, type = ButtonType.submit).text("Update")
                }
            }
            form.on(preventDefault = true).submit {
                println("SUBMIT! title=${titleVar.value} body=${bodyVar.value} status=${statusVar.value}")
                onSubmit(titleVar.value, bodyVar.value, statusVar.value)
            }
        }
    }
}

なお、select, input, required, initialValue の interface が統一感ないのは PR マージ済みなので次回以後のアップデートで修正される予定です。 全般、現在の kweb は実用にはちょっと早いかなという感じはしつつも、方向性は面白いなと思っているというのが現時点での感想。