Ktor 3.0.0-beta-2 Help

HTML DSL

HTML DSL integrates the kotlinx.html library into Ktor and allows you to respond to a client with HTML blocks. With HTML DSL, you can write pure HTML in Kotlin, interpolate variables into views, and even build complex HTML layouts using templates.

Add dependencies

HTML DSL doesn't need installation but requires the ktor-server-html-builder artifact. You can include it in the build script as follows:

implementation("io.ktor:ktor-server-html-builder:$ktor_version")
implementation "io.ktor:ktor-server-html-builder:$ktor_version"
<dependency> <groupId>io.ktor</groupId> <artifactId>ktor-server-html-builder-jvm</artifactId> <version>${ktor_version}</version> </dependency>

Send HTML in response

To send an HTML response, call the respondHtml method inside the required route. The example below shows a sample HTML DSL and a corresponding HTML to be sent to the client:

import io.ktor.server.application.* import io.ktor.server.html.* import io.ktor.http.* import io.ktor.server.routing.* import kotlinx.html.* fun Application.module() { routing { get("/") { val name = "Ktor" call.respondHtml(HttpStatusCode.OK) { head { title { +name } } body { h1 { +"Hello from $name!" } } } } } }
<html> <head> <title>Ktor</title> </head> <body> <h1>Hello from Ktor!</h1> </body> </html>

The following example shows how to respond with an HTML form used to collect credential information from a user:

get("/login") { call.respondHtml { body { form(action = "/login", encType = FormEncType.applicationXWwwFormUrlEncoded, method = FormMethod.post) { p { +"Username:" textInput(name = "username") } p { +"Password:" passwordInput(name = "password") } p { submitInput() { value = "Login" } } } } } }
<html> <body> <form action="/login" enctype="application/x-www-form-urlencoded" method="post"> <p>Username:<input type="text" name="username"></p> <p>Password:<input type="password" name="password"></p> <p><input type="submit" value="Login"></p> </form> </body> </html>

You can learn how to receive form parameters on the server side from Form parameters.

Templates

In addition to generating plain HTML, Ktor provides a template engine that can be used to build complex layouts. You can create a hierarchy of templates for different parts of an HTML page, for example, a root template for the entire page, child templates for a page header and footer, and so on. Ktor exposes the following API for working with templates:

  1. To respond with an HTML built based on a specified template, call the respondHtmlTemplate method.

  2. To create a template, you need to implement the Template interface and override the Template.apply method providing HTML.

  3. Inside a created template class, you can define placeholders for different content types:

    • Placeholder is used to insert the content. PlaceholderList can be used to insert the content that appears multiple times (for example, list items).

    • TemplatePlaceholder can be used to insert child templates and create nested layouts.

Example

Let's see on the example of how to create a hierarchical layout using templates. Imagine we have the following HTML:

<body> <h1>Ktor</h1> <article> <h2>Hello from Ktor!</h2> <p>Kotlin Framework for creating connected systems.</p> </article> </body>

We can split the layout of this page into two parts:

  • A root layout template for a page header and a child template for an article.

  • A child template for the article content.

Let's implement these layouts step-by-step:

  1. Call the respondHtmlTemplate method and pass a template class as a parameter. In our case, this is the LayoutTemplate class that should implement the Template interface:

    get("/") { call.respondHtmlTemplate(LayoutTemplate()) { // ... } }

    Inside the block, we will be able to access a template and specify its property values. These values will substitute placeholders specified in a template class. We'll create LayoutTemplate and define its properties in the next step.

  2. A root layout template will look in the following way:

    class LayoutTemplate: Template<HTML> { val header = Placeholder<FlowContent>() val content = TemplatePlaceholder<ContentTemplate>() override fun HTML.apply() { body { h1 { insert(header) } insert(ContentTemplate(), content) } } }

    The class exposes two properties:

    • The header property specifies a content inserted within the h1 tag.

    • The content property specifies a child template for article content.

  3. A child template will look as follows:

    class ContentTemplate: Template<FlowContent> { val articleTitle = Placeholder<FlowContent>() val articleText = Placeholder<FlowContent>() override fun FlowContent.apply() { article { h2 { insert(articleTitle) } p { insert(articleText) } } } }

    This template exposes the articleTitle and articleText properties, whose values will be inserted inside the article.

  4. Now we are ready to send HTML built using the specified property values:

    get("/") { call.respondHtmlTemplate(LayoutTemplate()) { header { +"Ktor" } content { articleTitle { +"Hello from Ktor!" } articleText { +"Kotlin Framework for creating connected systems." } } } }

You can find the full example here: html-templates.

Last modified: 02 April 2024