-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
htmx: use thymeleaf instead of kotlinx.html
kotlinx.html does not really support html fragments. For example, I can't respond with "<li>foo</li>". Instead I have to respond with "<body><ul><li>foo</li></ul></body>" which does not work with htmx when swapping a li element. See: Kotlin/kotlinx.html#228
- Loading branch information
Showing
7 changed files
with
77 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,45 @@ | ||
package kotlinbook | ||
|
||
import io.ktor.server.application.* | ||
import io.ktor.server.html.* | ||
import io.ktor.server.routing.* | ||
import io.ktor.server.thymeleaf.* | ||
import io.ktor.server.webjars.* | ||
import kotlinbook.web.WebResponse | ||
import kotlinbook.web.WebResponseSupport | ||
import kotlinx.html.BODY | ||
import kotlinx.html.HTML | ||
import kotlinx.html.body | ||
import kotlinx.html.button | ||
import kotlinx.html.h1 | ||
import kotlinx.html.head | ||
import kotlinx.html.p | ||
import kotlinx.html.script | ||
import kotlinx.html.title | ||
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver | ||
import java.time.LocalTime | ||
|
||
data class ListItem(val id: Int, val time: LocalTime) | ||
|
||
fun Application.initHtmxRoutes() { | ||
install(Webjars) | ||
install(Thymeleaf) { | ||
setTemplateResolver(ClassLoaderTemplateResolver().apply { | ||
prefix = "templates/" | ||
suffix = ".html" | ||
characterEncoding = "utf-8" | ||
}) | ||
} | ||
|
||
routing { | ||
get("/htmx", WebResponseSupport.webResponse { | ||
WebResponse.HtmlWebResponse(HtmxLayout("HTMX").apply { | ||
pageBody { | ||
h1 { | ||
+"HTMX Demo" | ||
} | ||
button { | ||
attributes["hx-get"] = "/htmx/click-me" | ||
attributes["hx-swap"] = "outerHTML" | ||
+"Click me!" | ||
} | ||
} | ||
}) | ||
WebResponse.ThymeleafWebResponse( | ||
"index", mapOf( | ||
"listItems" to (1..100).map { listItemId -> | ||
ListItem(listItemId, LocalTime.now()) | ||
}) | ||
) | ||
}) | ||
get("/htmx/click-me", WebResponseSupport.webResponse { | ||
WebResponse.HtmlWebResponse(FragmentLayout().apply { | ||
fragment { | ||
p { +"I have been clicked." } | ||
} | ||
}) | ||
WebResponse.ThymeleafWebResponse("click-me") | ||
}) | ||
get("/htmx/list-item/{id}", WebResponseSupport.webResponse { | ||
val id = checkNotNull(call.parameters["id"]).toInt() | ||
WebResponse.ThymeleafWebResponse( | ||
"list-item", mapOf( | ||
"item" to ListItem(id, LocalTime.now()) | ||
) | ||
) | ||
}) | ||
} | ||
} | ||
|
||
private class HtmxLayout( | ||
val pageTitle: String? = null | ||
) : Template<HTML> { | ||
val pageBody = Placeholder<BODY>() | ||
|
||
override fun HTML.apply() { | ||
val pageTitlePrefix = if (pageTitle == null) { | ||
"" | ||
} else { | ||
"$pageTitle - " | ||
} | ||
head { | ||
title { | ||
+"${pageTitlePrefix}KotlinBook" | ||
} | ||
script(src = htmx("dist/htmx.min.js")) {} | ||
script(src = htmx("dist/ext/json-enc.js")) {} | ||
script(src = htmx("dist/ext/sse.js")) {} | ||
} | ||
body { | ||
insert(pageBody) | ||
} | ||
} | ||
|
||
companion object { | ||
private val htmx = { e: String -> "webjars/htmx.org/1.9.4/$e" } | ||
} | ||
} | ||
|
||
private class FragmentLayout() : Template<HTML> { | ||
val fragment = Placeholder<BODY>() | ||
override fun HTML.apply() { | ||
body { | ||
insert(fragment) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<html> | ||
<p>I have been clicked.</p> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<html xmlns:th="http://www.thymeleaf.org"> | ||
<head> | ||
<script src="webjars/htmx.org/1.9.4/dist/htmx.min.js"></script> | ||
<script src="webjars/htmx.org/1.9.4/dist/ext/json-enc.js"></script> | ||
<script src="webjars/htmx.org/1.9.4/dist/ext/sse.js"></script> | ||
<title>HTXM Demo - Kotlinbook</title> | ||
</head> | ||
<body> | ||
<h1>HTMX Demo</h1> | ||
<button hx-get="/htmx/click-me" hx-swap="outerHTML">Click me!</button> | ||
<ol> | ||
<li th:each="item : ${listItems}" | ||
th:id="'listItem' + ${item.id}" | ||
th:hx-get="'/htmx/list-item/' + ${item.id}" | ||
hx-swap="outerHTML" | ||
th:text="'List item ' + ${item.id} + ' updated at ' + ${item.time}"> | ||
</li> | ||
</ol> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<html xmlns:th="http://www.thymeleaf.org"> | ||
<li | ||
th:id="'listItem' + ${item.id}" | ||
th:hx-get="'/htmx/list-item/' + ${item.id}" | ||
hx-swap="outerHTML" | ||
th:text="'List item ' + ${item.id} + ' updated at ' + ${item.time}"> | ||
</li> | ||
</html> |