Let's walk through this concept of generating bindings to a third-party library to modify our web page using jQuery through our Kotlin code. To do this we're going to need to find TypeScript bindings for jQuery, convert those to Kotlin with ts2kt, and then use those bindings to manipulate our page from Kotlin.
By following these steps, we'll be able to add HTML elements to our web page programmatically from our Kotlin code:
- First, install the ts2kt tool using the following npm command: npm -g install ts2kt.
- Then, from the root directory of our project, install jQuery on your machine using npm install jquery. We'll need to test our project in our local development environment. This should result in a node_modules directory being added to the root level of the project. Within that folder, you should see a jquery directory.
- Next, download the jquery.d.ts TypeScript definition file and save it to your root project directory. You can find the definitions here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/types/jquery/jquery.d.ts.
- We can then convert those headers into Kotlin with the following command: ts2kt -d src jquery.d.ts. This will generate a src/jquery.kt file under the root directory. This file will contain all the required Kotlin bindings for jQuery. If you open the file, you'll notice most of the bindings are implemented as external interface.
At this point, we're ready to start using jQuery within our Kotlin code. Let's start off by adding a basic header to our page. To do so, we can use the following code:
fun main() {
val outputMessage = "Hello Kotlin JavaScript"
println(outputMessage)
jQuery("body").append("<h1>We Added A Heading!!</h1>")
...
}
Running the code will append an <h1> tag to our <body> element when our script is loaded. Before we can see the results of this change, we need to include jquery.js as a script within index.html. This is what will allow our jQuery bindings to bind to the actual jQuery implementations. To include our local jQuery installation, add the following <script> tag to index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HelloKotlinJS</title>
</head>
<body bgcolor="#E6E6FA">
<script src="node_modules/jquery/dist/jquery.js"></script>
<script type="text/javascript"
src="out/production/ch14/lib/kotlin.js"></script>
<script type="text/javascript"
src="out/production/ch14/ch14.js"></script>
</body>
</html>
Now, we can rebuild our project and then reload index.html in our browser. Once you do, your page should now look like this:
You can see that our <h1> element has been successfully added to our page. This is a small visual change, but a pretty large conceptual step. We were able to generate bindings for a popular JavaScript library, leverage those bindings from Kotlin, and use them to manipulate the content of our web page using a statically typed API.
Now, let's expand on this a bit by leveraging more Kotlin features to generate a more interesting web page. Here's how this is done:
- Let's start by creating a ViewState data class that will contain the information to display on the page:
data class ViewState(val title: String, val topics: List<String>)
- Next, we'll create a PagePresenter class that will omit ViewState instances through a callback:
class PagePresenter(private val viewStateListener: (ViewState) -> Unit) {
init {
viewStateListener(ViewState("Hello KotlinJS", headings))
}
}
- We'll also define a list of topics that can be passed to our ViewState:
private val headings = listOf("Kotlin", "Programming", "JavaScript")
- Now, within main.kt, we can create a new instance of PagePresenter. Within the callback lambda, we can use jQuery to bind our ViewState properties to our web page:
val presenter = PagePresenter() {
jQuery("body").append("<h1>${it.title}</h1>")
it.topics.forEach {
jQuery("body").append("<h2>${it}</h2>")
}
}
Notice that within this callback, we're able to take advantage of Kotlin features such as String templates, and our Kotlin standard library functions such as forEach(). This makes it very easy to bind our ViewState to the UI by calling the appropriate jQuery functions.
If we rebuild this project and reload our web page, you should see that it now has a title and three subheadings:
This example has shown how to start building for the web using JavaScript that is transpiled from type-safe Kotlin code. When writing in Kotlin, we can take advantage of familiar Kotlin features such as data classes and the Kotlin standard library and rely on the compiler to generate appropriate JavaScript for us. The ability to use existing, or generate new, JavaScript bindings for popular libraries means we aren't limited in how we can write JavaScript. Whether we want to use jQuery, React, Redux, Node.js, or other frameworks, the possibility of using Kotlin is available to us. In Chapter 15, Introducing Multiplatform Kotlin, we'll build on another, more interactive, example of using Kotlin for web development as we work within a multiplatform project.