Web App With Kotlin.js: Getting Started
In this tutorial, you’ll learn how to create a web app using Kotlin.js. This will include manipulating the DOM and fetching data from a server, all in Kotlin! By Ahmed Tarek.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Web App With Kotlin.js: Getting Started
25 mins
- Why Kotlin.js?
- Getting Started
- Creating the Main Function
- Calling JavaScript Code From Kotlin
- Representing Books
- Architecting the App
- Fetching Data From the Server
- Building the UI
- Changing the Loader Visibility
- Building Book Elements
- Binding the Data
- Applying CSS
- Creating Cards
- Showing the Book Store Page
- Where to Go from Here?
Changing the Loader Visibility
Update the showLoader()
and hideLoader()
methods in BookStorePage
in the following way:
override fun showLoader() {
loader.style.visibility = "visible"
}
override fun hideLoader() {
loader.style.visibility = "hidden"
}
Again, you use the usual DOM APIs to change the visibility property of the elements to either "visible"
or "hidden"
, as required.
The loader element is visible by default, so you should see it when you open the index.html page.
Test your code and hide the loader by adding the updating the main()
function to the following:
fun main(args: Array<String>) {
val bookStorePresenter = BookStorePresenter()
val bookStorePage = BookStorePage(bookStorePresenter)
bookStorePage.hideLoader()
}
You’ve updated the main function to directly call hideLoader()
to hide the spinner that was visible before.
Build the project and refresh index.html in your browser. The loader should now be gone!
Building Book Elements
Next, you’ll build cards for each book to display, like this one:
Create a new class and name it CardBuilder
. In this class, you’ll build an HTMLElement
to present the book, bind the books’ details to it, and apply CSS. Start by updating the class to the following:
class CardBuilder {
fun build(book: Book): HTMLElement {
// 1
val containerElement = document.createElement("div") as HTMLDivElement
val imageElement = document.createElement("img") as HTMLImageElement
val titleElement = document.createElement("div") as HTMLDivElement
val priceElement = document.createElement("div") as HTMLDivElement
val descriptionElement = document.createElement("div") as HTMLDivElement
val viewDetailsButtonElement = document.createElement("button") as HTMLButtonElement
// 2
bind(book = book,
imageElement = imageElement,
titleElement = titleElement,
priceElement = priceElement,
descriptionElement = descriptionElement,
viewDetailsButtonElement = viewDetailsButtonElement)
// 3
applyStyle(containerElement,
imageElement = imageElement,
titleElement = titleElement,
priceElement = priceElement,
descriptionElement = descriptionElement,
viewDetailsButtonElement = viewDetailsButtonElement)
// 4
containerElement
.appendChild(
imageElement,
titleElement,
descriptionElement,
priceElement,
viewDetailsButtonElement
)
// 5
return containerElement
}
// 6
private fun Element.appendChild(vararg elements: Element) {
elements.forEach {
this.appendChild(it)
}
}
}
There’s a lot to do here, so let’s look at the steps one at a time:
- Create new elements by using the
createElement()
browser API, passing in the name of the HTML tag to create. For example, use"div"
to create anHTMLDivElement
and"img"
to create anHTMLImageElement
. - Bind the book data to the HTML elements you created. You will implement this
bind()
method soon. - Apply some CSS classes to the HTML elements you created. You will also implement the
applyStyle()
method below. - Append all of the individual HTML elements to one container.
- Return the container, which is the root element of the card.
- Write an extension function that enables you to append a variable number of children to an element, instead of having to call the regular
appendChild()
method many times.
Binding the Data
To populate the elements with data, add the following method to the CardBuilder
class.
private fun bind(book: Book,
imageElement: HTMLImageElement,
titleElement: HTMLDivElement,
priceElement: HTMLDivElement,
descriptionElement: HTMLDivElement,
viewDetailsButtonElement: HTMLButtonElement) {
// 1
imageElement.src = book.coverUrl
// 2
titleElement.innerHTML = book.title
priceElement.innerHTML = book.price
descriptionElement.innerHTML = book.description
viewDetailsButtonElement.innerHTML = "view details"
// 3
viewDetailsButtonElement.addEventListener("click", {
window.open(book.url)
})
}
In this method, you:
- Set the book cover image URL as the source of the image element on the card.
- Set the text content for the various text elements.
- Add a click event listener to the button element, which will navigate to the book’s URL if the button is clicked.
Applying CSS
The other method still missing is applyStyle()
, which you should also add to the CardBuilder
class.
private fun applyStyle(containerElement: HTMLDivElement,
imageElement: HTMLImageElement,
titleElement: HTMLDivElement,
priceElement: HTMLDivElement,
descriptionElement: HTMLDivElement,
viewDetailsButtonElement: HTMLButtonElement) {
containerElement.addClass("card", "card-shadow")
imageElement.addClass("cover-image")
titleElement.addClass("text-title", "float-left")
descriptionElement.addClass("text-description", "float-left")
priceElement.addClass("text-price", "float-left")
viewDetailsButtonElement.addClass("view-details", "ripple", "float-right")
}
This method adds the proper CSS classes that you need to style the book card with a material design style. You can find these classes already set up in the styles.css file. For example, the card-shadow
CSS class gives a material shadow to the card container, and the float-left
CSS class aligns the element to the left.
Creating Cards
Let’s go back to the BookStorePage
class and start using this card creation code. First, add a property to the class, which will store an instance of CardBuilder
.
private val cardBuilder = CardBuilder()
Then, go to the showBooks()
method and add the following code:
books.forEach { book ->
val card = cardBuilder.build(book)
content.appendChild(card)
}
This code iterates through the list of books, and for each book, builds an HTML element representing it. Then, it adds the element to the content <div>
we looked up from the DOM earlier.
Showing the Book Store Page
You’re almost done now. Add the following method to the BookStorePage
class:
fun show() {
presenter.attach(this)
presenter.loadBooks()
}
This code sets the current BookStorePage
instance as the presenter’s view so that it can receive callbacks from it, and then it asks the presenter to start loading the books.
Go to the main()
function and update it to call this show()
method on bookStorePage
. The entire main()
method should now look like this:
fun main(args: Array<String>) {
val bookStorePresenter = BookStorePresenter()
val bookStorePage = BookStorePage(bookStorePresenter)
bookStorePage.show()
}
Build the project and refresh index.html.
You should see the loader briefly before the app finishes loading the books. Then the book cards will appear. The cards should have a shadow when you hover over them, and the View Details button should navigate you to the appropriate page for the book.
Hooray! You have created your first web app in Kotlin :]
Where to Go from Here?
You can download the files for the completed project (as well as the starter project) by clicking on the Download Materials button at the top or bottom of the tutorial.
We’ve covered the basics of using Kotlin.js to build web apps with Kotlin in the browser, but there’s a lot more to discover on this topic.
If you’re interested in setting up a more advanced project and development environment, you can learn about building Kotlin.js projects with Gradle, unit testing Kotlin code with JavaScript test frameworks, and even about debugging Kotlin in the browser.
Finally, you can take a look at how to call a JavaScript function from Kotlin as if it was a static method.
If you have any questions or comments, join in on the forum discussion below! We are happy to hear from you :]