8 minutes read

You already know what HTML is, and why you need it. You can work with HTML as with plain text, but it's not always convenient. Kotlin provides us with tools that make it easy to generate HTML code. In this topic, we will get acquainted with these tools.

Getting started

The kotlinx.html library provides us with a handy tool for creating an HTML code: Kotlin HTML DSL. It saves you from working with strings when creating an HTML code. In fact, HTML DSL is a special language that makes it easy to specify HTML directly in the application code without using templating tools.

To make HTML DSL available in your project, you need to include a dependency in build.gradle.kts:

implementation("org.jetbrains.kotlinx:kotlinx-html:0.8.1")

The actual version can find in the Maven Repository.

Then import it in the code file:

import kotlinx.html.*
import kotlinx.html.dom.*

fun main() {

}

Great! Now we can start working with HTML DSL.

Create HTML document

First, we need to create a document that we will fill with content. This is done as follows:

val myDocument = document { }

If you work with Kotlin on the JS platform, by default you will have: kotlin.browser.document. On the JVM, we have to create the document manually.

We can use the myDocument.append function to generate and add HTML to our document. This function takes a template of HTML code written in the HTML DSL language as an input. With this language, we can specify any nesting of tags and substitute values in the template with the + symbol. The easiest way to understand this is to see a concrete example:

myDocument.append {
    html {
        head {
            title {
                +"My html page"
            }
        }
        body {
            h1 {
                +"Hello user!"
            }
        }
    }
}

Now let's output the resulting HTML document to the console. To get the generated HTML code of our document, we use myDocument.serialize() method.

println(myDocument.serialize())

Result output:

<!DOCTYPE html>
<html>
    <head>
        <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>My html page</title>
    </head>
    <body>
        <h1>Hello user!</h1>
    </body>
</html>

As you can see, we created an HTML document right in our code without having to deal with the tags and the strings. This is the advantage of HTML DSL. This language is built entirely on Kotlin features such as lambda functions with a receiver, trailing lambda and operator overloading mechanism. If you want to know more about HTML DSL, refer to the corresponding explanation in the documentation. Our task now is to learn how to use it.

Substituting a variable value

HTML DSL allows to substitute in a template not only specific string values but also values from variables. The + operator is used for this as well:

val greeting = "Hello user!"
myDocument.append {
    html {
        body {
            h1 {
                +greeting
            }
        }
    }
}

The result of calling println(myDocument.serialize()):

<!DOCTYPE html>
<html>
    <body>
        <h1>Hello user!</h1>
    </body>
</html>

Embedding a loop

The next important thing you need to know is how to embed the loop in the template. You rarely know how many tags you will have to create. Imagine you have a site where users can leave comments. You don't know in advance how many comments you have to display.

Let's say you have a MutableList, which contains the current comments you want to output. To do that, you just need to wrap the repeating part of the pattern in a for loop:

val comments = mutableListOf("Hello, everyone!", "Great site", "Nice :)")
myDocument.append {
    html {
        body {
            for (comment in comments) {
                div {
                    +comment
                }
            }
        }
    }
}

Result HTML:

<!DOCTYPE html>
<html>
    <body>
        <div>Hello, everyone!</div>
        <div>Great site</div>
        <div>Nice :)</div>
    </body>
</html>

Setting HTML attributes

We can set the content of HTML elements with the + operator. How can we set element's attributes?

Let's look at the following code:

myDocument.append {
    html {
        body {
            a {
                +"visit us"
            }
        }
    }
}

Result HTML:

<!DOCTYPE html>
<html>
    <body>
        <a>visit us</a>
    </body>
</html>

We have a page with a single link. We set the text of the link to "visit us". Since you're already familiar with HTML, you know that to make a link valid, you also need to specify the destination address via the href attribute. To do this, you need to use the attributes object. This object is available inside an element block and allows you to assign attributes to it:

 htmlElement {
    attributes["attributeName"] = "attributeValue"

    +"htmlElement's content"
}

In our case:

a {
    attributes["href"] = "hyperskill.org"
    +"visit us"
}

Now our link will be correct:

<a href="hyperskill.org">visit us</a>

If we want to set several attributes, we can simply set them in a row using the same attributes object:

 htmlElement {
    attributes["attributeName"] = "attributeValue"
    attributes["attributeName2"] = "attributeValue2"
    ...
    attributes["attributeNameN"] = "attributeValueN"

    +"htmlElement's content"
}

Let's add a class attribute to our link, which we may need later for styling:

a {
    attributes["href"] = "hyperskill.org"
    attributes["class"] = "mylink"
    +"visit us"
}

Our link:

<a class="mylink" href="hyperskill.org">visit us</a>

Some attributes are used very often in HTML. That's why the developers put some attributes into function parameters of the corresponding element. They can be set faster this way. Each HTML element has its own list of attributes, which we can set through parameters. For example, for a link element <a> we can set the href and class through parameters:

a(href = "hyperskill.org", classes = "mylink") {
    +"visit us"
}

It's just a shorter way to set our link.

If we want to specify other attributes for the link, we should set them in the usual way using the attributes object.

Creating HTML elements

In the previous sections, we showed you how to create an HTML page using the myDocument.append method. Now we'll look at another important method, myDocument.createElement. This method lets you create individual HTML elements and work with them as separate objects. This is done as:

val myElement = myDocument.createElement("htmlTag")

Let's create a div element:

val myDiv = myDocument.createElement("div")

Then we can use the myDiv.append method to fill the element with the content:

myDiv.append {
    i {
        +"Hyperskill"
    }
}

We can get the contents of myDiv using the serialize method you are already familiar with:

println(myDiv.serialize())

Result:

<div>
    <i>Hyperskill</i>
</div>

Adding elements to the document

Besides creating individual elements, the kotlinx.html library also allows you to add them to an existing document.

Let's create the following HTML document:

val myDocument = document { }
myDocument.append {
    html {
        body {
            div {
                attributes["id"] = "mainDiv"
            }
        }
    }
}

We created a plain HTML document with an empty div with id = "mainDiv". We are going to add new elements into it.

<!DOCTYPE html>
<html>
    <body>
        <div id="mainDiv"></div>
    </body>
</html>

To add elements to our empty div, we need to get it using the getElementById method:

val mainDiv = myDocument.getElementById("mainDiv")

Now create a new div element, as in the previous section, and add it to our mainDiv using the appendChild method:

val newDiv = myDocument.createElement("div")
newDiv.append {
    i {
        +"Hyperskill"
    }
}

mainDiv.appendChild(newDiv)

If you display the complete document, you see that our new element has been successfully added to the right part of the document.

println(myDocument.serialize())

Result:

<!DOCTYPE html>
<html>
    <body>
        <div id="mainDiv">
            <div>
                <i>Hyperskill</i>
            </div>
        </div>
    </body>
</html>

We used the getElementById method to get a reference to an empty div, and then added a new element to it using the appendChild method.

Note that using the getElementById function, we don't create a new element. We just get a reference to an existing element in the DOM of our myDocument. That's why after adding content to the mainDiv using the appendChild method, not only the mainDiv itself has changed but also the entire document.

Conclusion

In this topic, we introduced the HTML DSL.

You've learned:

  • How to construct HTML directly in Kotlin code.

  • How to use loops to display lists.

  • How to set the attributes of HTML elements.

  • How to create new HTML elements and add them to an existing document.

For more information about the kotlinx.html library, you can always refer to its documentation.

Don't worry if you don't remember something from this topic. You can always go back to the theory. Now let's put what we've learned into practice.

26 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo