Kotlin / kotlinx.html

Kotlin DSL for HTML
Apache License 2.0
1.6k stars 130 forks source link

`attributes["hx-on::after-request"]` does not preserve double colon #267

Open davidchambers opened 4 months ago

davidchambers commented 4 months ago

I'm trying to use the approach suggested in https://github.com/bigskysoftware/htmx/issues/1698#issuecomment-1704361409 to reset a form after successful submission.

I'm having trouble with attributes["hx-on::after-request"]: only one colon appears in the rendered HTML.

I'm using .replace("hx-on:after-request", "hx-on::after-request") as a workaround. Can you suggest a better solution?

severn-everett commented 3 months ago

Would you be able to give a more detailed list of reproduction steps? This code that gets inserted into AttributesTest.kt on the master branch passes:

    @Test
    fun testDoubleColon() {
        val html = buildString {
            appendHTML(false).form {
                attributes["hx-on::after-request"] = "if(event.detail.successful) this.reset()"
            }
        }
        assertEquals("<form hx-on::after-request=\"if(event.detail.successful) this.reset()\"></form>", html)
    }
davidchambers commented 3 months ago

Here's a simplified version of my starting point:

createHTMLDocument().html {
    body {
        form {
            attributes["hx-on::after-request"] = "if (event.detail.successful) this.reset()"
        }
    }
}.serialize()

This crashes with java.lang.RuntimeException: Namespace for prefix 'hx-on' has not been declared.

I made the following change:

 createHTMLDocument().html {
+    attributes["xmlns:hx-on"] = "http://www.w3.org/1999/xhtml"
     body {
         form {
             attributes["hx-on::after-request"] = "if (event.detail.successful) this.reset()"
         }
     }
 }.serialize()

This version doesn't crash, but the resulting HTML is missing a colon.

Interestingly, replacing "hx-on::after-request" with "hx-on:htmx:after-request" does not change the resulting HTML.

severn-everett commented 3 months ago

The immediate cause is that Java's XML parsing library views the colons as part of a namespace-based declaration, so it (unsuccessfully) attempts to look up the namespace hx-on as your POC demonstrates. I'd defer to the lib owners like @e5l as to whether this is functionality that should be supported, but in the meantime, you could follow HTMX's recommendation to use dashes instead of colons, e.g. hx-on--after-request.