logoalt Hacker News

t-writescodeyesterday at 5:13 PM1 replyview on HN

To build reusable components, I end up using a mix of a lot of extension functions and Kotlin's function pointer syntax.

So, the components themselves will look something like this:

    fun HtmlBlockTag.radioButtonWithLabel(
        groupName: String,
        id: String,
        hidden: Boolean = false,
        radioButtonFunc: (INPUT.() -> Unit)? = null,
        func: LABEL.() -> Unit
    ) {
        radioInput(name=groupName) {
            this.id = id
            this.hidden = hidden
            radioButtonFunc?.invoke(this)
        }
        label { this.htmlFor = id; func() }
    }
And then use of them will be like this:

  call.respondHtml {
      body {
          div(CSS_CLASS_NAME) {
              radioButtonWIthLabel(MORE_CSS_CLASS_NAME, "group", "id") {
                  +"Text for the label"
              }
          }
      }
  }
More complicated examples just extend that quite a lot.

I've also got whole files dedicated to single extension functions that end up being a whole section that I can place anywhere.

---

And then to test those single-function components, I'll do something like this:

  class SingleSectionTest {
      private suspend fun ApplicationTestBuilder.buildApplicationAndCall(
          data: DataUsedForSection
      ): Document {
            application {
                routing {
                    get("test") {
                        call.respondHtml {
                            body {
                                renderSingleSection(data)
                            }
                        }
                    }
                }
            }
    
            val response = client.get("test")
            val body = Jsoup.parse(response.bodyAsText())
    
            return body;
        }

      @Test
      fun `simple test case`() = testApplication {
          val data = DataUsedForSection("a", "b", "c")
          val body = buildApplicationAndCall(data)
          
          // all the asserts
      }
  }
And so on. Is this what you were wondering? Or would you like a different sort of example?

Replies

catgirlinspacetoday at 1:38 AM

That's pretty much what I was looking for, thank you for sharing! I think that's probably the nicest way I've seen to do it, annoying that Kotlin seems to force you to add it as a child (? idk the word...) of an existing HTML tag, wish you could just import a component or something :(

show 1 reply