Tech

Web App With Kotlin.js: Getting Started

Web App With Kotlin.js: Getting Started

Because the announcement of official help for Kotlin on Android at Google I/O 2017, using Kotlin has massively accelerated inside the Android group.

However Kotlin can be utilized for rather more than simply Android. You should use Kotlin instead of Java in back-end methods. You’ll be able to even use Kotlin on the front-end, changing JavaScript as an internet language. Kotlin has the potential to be a real full-stack answer, being in use on the server, within the net browser, and on cellular.

Why Kotlin.js?

    So, why would you employ Kotlin for net improvement? Listed here are a number of causes:

  • Familiarity: Should you’re coming from a compiled language like Java, Swift or C#, you’ll discover Kotlin very straightforward to study — and also you may already be acquainted with it in case you’re an Android developer.
  • Pleasant instruments: IDEs can’t allow you to a lot with JavaScript, whereas Kotlin comes with first-class IDE help so as to spot widespread errors as you sort the code.
  • Sharing code between platforms: With Kotlin Multiplatform Tasks, you’ll be able to write the enterprise logic of your app as soon as, and share it throughout many platforms together with your back-end, browser front-end, Android and iOS shoppers.
  • Interoperability: The power to name JavaScript code out of your Kotlin code is essential. It permits you to reuse present JavaScript code you’ve already written with Kotlin. This interop works in the other way as nicely. You possibly can name your Kotlin code from JavaScript.
  • JavaScript woes: Kotlin is an ideal selection for those who gave up on net improvement due to widespread JavaScript points, comparable to having to cope with dynamic typing, bizarre logical comparisons, or prototypes.
Conditions: For this tutorial, you want a primary information of net programming and a familiarity with Kotlin and IntelliJ IDEA. In case you’re utterly new to Kotlin, you may need to take a look at the Kotlin Apprentice e-book or the Programming in Kotlin video course first.

Getting Started

You’re going to construct a bookstore app for raywenderlich.com. The app will fetch knowledge concerning the books from an internet service, show the e-book covers with titles, descriptions and costs, in addition to a button to open a e-book’s particulars web page on raywenderlich.com. Right here’s what the top product will seem like:

End Product

To comply with together with this tutorial, you’ll want to make use of IntelliJ IDEA 2018.2.7 or later (the free Group Version is sweet sufficient), and Kotlin 1.2.61 or later.

Begin by downloading the supplies for this tutorial utilizing the Obtain Supplies button on the prime or backside of this web page. Then hearth up IntelliJ IDEA and create a brand new venture.

Within the New Undertaking window, choose Kotlin from the left aspect panel and Kotlin/JS on the fitting. Then, click on Subsequent.

New Project Step 1

For the challenge identify, use bookstore. Choose a challenge location, or use the default. Then click on End.

New Project Step 2

Unzip the supplies you’ve downloaded, and from the bookstore-starter folder, copy the index.html and types.css information to your venture’s root folder. The undertaking construction ought to seem like the next:

Project Anatomy

Creating the Major Perform

Create a brand new Kotlin file with the identify Essential.kt within the src listing and add the primary() perform as proven under:


enjoyable foremost(args: Array<String>)
println(“Hello world!”)

Observe: The app’s most important() perform might be in any Kotlin file with any identify, so utilizing Essential.kt because the filename right here is just not strictly required, however you need to solely have one major() perform in your challenge.

Subsequent, open the Construct menu and click on on Construct Challenge to compile your Kotlin code to JavaScript. The IDE will generate a brand new folder referred to as out in your challenge’s root folder.

It’s worthwhile to reference two information from this out folder in index.html:

  • kotlin.js: This can be a distribution of the Kotlin normal library, carried out in JavaScript.
  • bookstore.js: That is the JavaScript that your personal Kotlin code was compiled to.

Notice: Each information are already referenced for you inside script tags within the starter index.html file, however you could have to examine their paths in case you entered a special venture identify than bookstore.

Lastly, open index.html in your browser, after which open the developer console. You need to see “Hello World!”, like the next screenshot:

Hello World in Dev Console

Word: Each time you modify your Kotlin code, you’ll have to construct your challenge after which refresh the HTML web page to see the modifications.

Calling JavaScript Code From Kotlin

Within the index.html file, inside a <script> tag, you’ll discover a JavaScript perform referred to as getApiUrl(), which returns the URL you should fetch the bookstore JSON knowledge from.


<script>
perform getApiUrl()
return “https://gist.githubusercontent.com/tarek360/4578e33621011e18829bad0c8d1c8cdf/raw/06d185bebc3e14a56dfa85f53288daddd4ff6a2b/books.json”;

</script>

There are lots of methods to entry a JavaScript perform or variable out of your Kotlin code. Certainly one of them is through the use of the js() perform, which lets you cross native JavaScript code as a string.

Add the next line of code to the Major.kt file, outdoors of the primary() perform.


val API_URL = js(“getApiUrl()”) as String

Right here, you move the string “getApiUrl()” to the js() perform. Because the getApiUrl() perform all the time returns a string, you possibly can forged it safely to a Kotlin String, and retailer it in a Kotlin worth.

Now, replace the primary() perform to print the worth of the API_URL property as an alternative of “Hello world!”.


enjoyable principal(args: Array<String>)
println(API_URL)

Construct the undertaking and refresh index.html in your browser. You need to see the worth of the API_URL variable printed to the console, like the next screenshot:

API URL in Dev Console

Now, you’ve got the URL saved within the API_URL worth, which you’ll use later.
Lastly, clear the primary() perform’s physique to prepare for what comes subsequent.

Representing Books

RW Books

To fetch guide knowledge from the server and current it on the UI, it’s essential to create a brand new Kotlin class to characterize a single e-book. Create a file named Guide.kt within the src folder and place this knowledge class in it:


knowledge class E-book(val title: String,
val worth: String,
val description: String,
val url: String,
val coverUrl: String)

Each ebook has a title, worth, description, a URL for its particulars web page on raywenderlich.com, and a canopy picture URL.

Architecting the App

You’ll use a primary MVP structure on this app. A presenter class will include all the enterprise logic, whereas a web page class will act because the view. Earlier than you create these courses, you’ll create the contract between them.

Create a brand new Kotlin interface referred to as BookStoreContract (as ordinary, in its personal file within the src folder) which defines the connection between the view and the presenter. Add the next code to it:


interface BookStoreContract
interface View
enjoyable showBooks(books: Record<E-book>) // 1
enjoyable showLoader() // 2
enjoyable hideLoader() // three


interface Presenter
enjoyable connect(view: View) // four
enjoyable loadBooks() // 5

The view will be capable of:

  1. Present an inventory of books offered to it.
  2. Present a loading indicator whereas the app is fetching the ebook knowledge from the server.
  3. Cover the loading indicator.

As for the presenter, it will possibly:

  1. Show outcomes on any view that it’s offered.
  2. Begin loading the ebook knowledge from the info supply. On this case, that’s a distant server.

With that accomplished, now you can create a BookStorePage class, and add the next code:


class BookStorePage(personal val presenter: BookStoreContract.Presenter) : BookStoreContract.View
override enjoyable showBooks(books: Record<Ebook>)

override enjoyable showLoader()

override enjoyable hideLoader()

This class has a constructor with a BookStoreContract.Presenter parameter. It implements the BookStoreContract.View interface with three required strategies (empty, for now).

Create a BookStorePresenter class and add the next code:


// 1
class BookStorePresenter : BookStoreContract.Presenter
// 2
personal lateinit var view: BookStoreContract.View
// three
override enjoyable connect(view: BookStoreContract.View)
this.view = view

// four
override enjoyable loadBooks()

On this class, you:

  1. Implement the BookStoreContract.Presenter interface.
  2. Add a lateinit property to maintain a reference to the view.
  3. Implement the connect() technique from the BookStoreContract.Presenter interface, and initialize the view property with the acquired parameter.
  4. Implement the loadBooks() technique required by the BookStoreContract.Presenter interface (empty, for now).

Fetching Knowledge From the Server

You want a option to fetch knowledge from the server. To do that, add the next technique to the BookStorePresenter class.


// 1
personal enjoyable getAsync(url: String, callback: (String) -> Unit)
// 2
val xmlHttp = XMLHttpRequest()
// three
xmlHttp.open(“GET”, url)
// four
xmlHttp.onload =
// 5
if (xmlHttp.readyState == four.toShort() && xmlHttp.standing == 200.toShort())
// 6
callback.invoke(xmlHttp.responseText)


// 7
xmlHttp.ship()

Hit choice+return on Mac or Alt+Enter on PC so as to add in an import for the XMLHttpRequest class.

Let’s go over what you’re doing right here, step-by-step.

  1. Create a brand new technique that makes a community request. It takes a URL to fetch from, in addition to a perform with a String parameter, which it should move the results of the community name to.
  2. Create a brand new XMLHttpRequest occasion.
  3. Set this request up in order that it sends an HTTP GET to the given URL.
  4. Set a callback which might be invoked when the request completes.
  5. Examine if the request is in a achieved (four) state, and if it has an OK (200) standing code.
  6. Name the callback perform acquired as a parameter, and cross it the contents of the community response as a single string.
  7. Invoke ship() to fireside off the HTTP request you’ve arrange.

With that achieved, now you can use this helper technique to implement loadBooks():


override enjoyable loadBooks()
//1
view.showLoader()
//2
getAsync(API_URL) response ->
//three
val books = JSON.parse<Array<Guide>>(response)
//four
view.hideLoader()
//5
view.showBooks(books.toList())

On this code, you:

  1. Ask the view to point out a loading indicator earlier than you begin loading the info.
  2. Make the asynchronous request to get the books’ knowledge.
  3. Parse the JSON response acquired as an array of situations of the Ebook knowledge class.
  4. Ask the view to cover the loading indicator, because you’ve completed loading and parsing.
  5. Ask the view to point out the listing of books.

You’ll be able to iterate the books array and print every guide.title to the console to ensure that every little thing works appropriately. To do that, add the next strains of code after the books have been parsed:


books.forEach guide ->
println(guide.title)

As a way to check out the presenter code, replace the primary() perform to learn:


enjoyable fundamental(args: Array<String>)
val bookStorePresenter = BookStorePresenter()
val bookStorePage = BookStorePage(bookStorePresenter)
bookStorePresenter.connect(bookStorePage)
bookStorePresenter.loadBooks()

Right here, you create a brand new occasion of BookStorePresenter, after which an occasion of BookStorePage, passing the web page the presenter occasion by way of its constructor. You then connect the web page to the presenter and name loadBooks() on the presenter immediately.

Construct and run the venture and refresh index.html. You must see a log like the next screenshot:

Books in Dev Console

When finished with testing, take away the forEach loop with the print assertion inside loadBooks().

Word: When you attempt printing the books themselves (println(e-book)), it’s regular to only see [object Object] repeated time and again within the output. It’s because the JSON.parse name constructs pure JavaScript objects as an alternative of calling the constructor of the Kotlin E-book class.

This implies you’ll have the ability to learn its properties, however any strategies you’d anticipate the category to have can be lacking – together with the auto-generated toString() implementation. For those who want a extra strong parsing answer that may do that appropriately, you possibly can check out the kotlinx.serialization library.

Constructing the UI

The index.html file accommodates two <div> tags with IDs, specifically “loader” and “content”. The previous is a loading indicator which you could present whereas your app is loading knowledge, and conceal when it’s completed loading. The latter one is a container that all the ebook playing cards can be added to.

To entry these DOM parts in your Kotlin code, add two new properties to the BookStorePage class as proven under.


personal val loader = doc.getElementById(“loader”) as HTMLDivElement
personal val content material = doc.getElementById(“content”) as HTMLDivElement

You’ll be able to all the time get a component within the DOM by its ID, utilizing the doc object and the getElementById() technique, identical to you’d in JavaScript.

The getElementById() technique returns a generic Component, which you’ll be able to forged to the extra particular factor sort in case you want (just like how the findViewById() technique used to work on Android).

Altering the Loader Visibility

Replace the showLoader() and hideLoader() strategies in BookStorePage within the following approach:


override enjoyable showLoader()
loader.type.visibility = “visible”

override enjoyable hideLoader()
loader.type.visibility = “hidden”

Once more, you employ the standard DOM APIs to vary the visibility property of the weather to both “visible” or “hidden”, as required.

The loader factor is seen by default, so you need to see it whenever you open the index.html web page.

Loading

Check your code and conceal the loader by including the updating the primary() perform to the next:


enjoyable important(args: Array<String>)
val bookStorePresenter = BookStorePresenter()
val bookStorePage = BookStorePage(bookStorePresenter)
bookStorePage.hideLoader()

You’ve up to date the primary perform to instantly name hideLoader() to cover the spinner that was seen earlier than.

Construct the venture and refresh index.html in your browser. The loader ought to now be gone!

Constructing Guide Parts

Subsequent, you’ll construct playing cards for every ebook to show, like this one:

Book Card

Create a brand new class and identify it CardBuilder. On this class, you’ll construct an HTMLElement to current the e-book, bind the books’ particulars to it, and apply CSS. Begin by updating the category to the next:


class CardBuilder

enjoyable construct(guide: Ebook): HTMLElement
// 1
val containerElement = doc.createElement(“div”) as HTMLDivElement
val imageElement = doc.createElement(“img”) as HTMLImageElement
val titleElement = doc.createElement(“div”) as HTMLDivElement
val priceElement = doc.createElement(“div”) as HTMLDivElement
val descriptionElement = doc.createElement(“div”) as HTMLDivElement
val viewDetailsButtonElement = doc.createElement(“button”) as HTMLButtonElement

// 2
bind(e-book = guide,
imageElement = imageElement,
titleElement = titleElement,
priceElement = priceElement,
descriptionElement = descriptionElement,
viewDetailsButtonElement = viewDetailsButtonElement)

// three
applyStyle(containerElement,
imageElement = imageElement,
titleElement = titleElement,
priceElement = priceElement,
descriptionElement = descriptionElement,
viewDetailsButtonElement = viewDetailsButtonElement)

// four
containerElement
.appendChild(
imageElement,
titleElement,
descriptionElement,
priceElement,
viewDetailsButtonElement
)
// 5
return containerElement


// 6
personal enjoyable Aspect.appendChild(vararg parts: Factor)
parts.forEach
this.appendChild(it)


There’s quite a bit to do right here, so let’s take a look at the steps separately:

  1. Create new parts through the use of the createElement() browser API, passing within the identify of the HTML tag to create. For instance, use “div” to create an HTMLDivElement and “img” to create an HTMLImageElement.
  2. Bind the guide knowledge to the HTML parts you created. You’ll implement this bind() technique quickly.
  3. Apply some CSS courses to the HTML parts you created. Additionally, you will implement the applyStyle() technique under.
  4. Append all the particular person HTML parts to at least one container.
  5. Return the container, which is the basis factor of the cardboard.
  6. Write an extension perform that lets you append a variable variety of youngsters to a component, as an alternative of getting to name the common appendChild() technique many occasions.

Binding the Knowledge

To populate the weather with knowledge, add the next technique to the CardBuilder class.


personal enjoyable bind(guide: Ebook,
imageElement: HTMLImageElement,
titleElement: HTMLDivElement,
priceElement: HTMLDivElement,
descriptionElement: HTMLDivElement,
viewDetailsButtonElement: HTMLButtonElement)

// 1
imageElement.src = e-book.coverUrl

// 2
titleElement.innerHTML = ebook.title
priceElement.innerHTML = e-book.worth
descriptionElement.innerHTML = guide.description
viewDetailsButtonElement.innerHTML = “view details”

// three
viewDetailsButtonElement.addEventListener(“click”,
window.open(ebook.url)
)

On this technique, you:

  1. Set the guide cowl picture URL because the supply of the picture component on the cardboard.
  2. Set the textual content content material for the varied textual content parts.
  3. Add a click on occasion listener to the button aspect, which can navigate to the ebook’s URL if the button is clicked.

Making use of CSS

The opposite technique nonetheless lacking is applyStyle(), which you also needs to add to the CardBuilder class.


personal enjoyable 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 technique provides the right CSS courses that you might want to fashion the e-book card with a cloth design fashion. Yow will discover these courses already arrange within the types.css file. For instance, the card-shadow CSS class provides a cloth shadow to the cardboard container, and the float-left CSS class aligns the component to the left.

Creating Playing cards

Let’s return to the BookStorePage class and begin utilizing this card creation code. First, add a property to the category, which can retailer an occasion of CardBuilder.


personal val cardBuilder = CardBuilder()

Then, go to the showBooks() technique and add the next code:


books.forEach ebook ->
val card = cardBuilder.construct(ebook)
content material.appendChild(card)

This code iterates by way of the record of books, and for every ebook, builds an HTML factor representing it. Then, it provides the component to the content material <div> we appeared up from the DOM earlier.

Displaying the Ebook Retailer Web page

You’re virtually finished now. Add the next technique to the BookStorePage class:


enjoyable present()
presenter.connect(this)
presenter.loadBooks()

This code units the present BookStorePage occasion because the presenter’s view in order that it could possibly obtain callbacks from it, after which it asks the presenter to start out loading the books.

Go to the primary() perform and replace it to name this present() technique on bookStorePage. The complete major() technique ought to now appear to be this:


enjoyable essential(args: Array<String>)
val bookStorePresenter = BookStorePresenter()
val bookStorePage = BookStorePage(bookStorePresenter)
bookStorePage.present()

Construct the venture and refresh index.html.

You need to see the loader briefly earlier than the app finishes loading the books. Then the guide playing cards will seem. The playing cards ought to have a shadow whenever you hover over them, and the View Particulars button ought to navigate you to the suitable web page for the e-book.

End Product

Hooray! You will have created your first net app in Kotlin :]

Happy Face

The place to Go from Right here?

You possibly can obtain the information for the finished challenge (in addition to the starter challenge) by clicking on the Obtain Supplies button on the prime or backside of the tutorial.

We’ve coated the fundamentals of utilizing Kotlin.js to construct net apps with Kotlin within the browser, however there’s much more to find on this matter.

In case you’re all for establishing a extra superior venture and improvement setting, you possibly can study constructing Kotlin.js tasks with Gradle, unit testing Kotlin code with JavaScript check frameworks, and even about debugging Kotlin within the browser.

Lastly, you’ll be able to check out tips on how to name a JavaScript perform from Kotlin as if it was a static technique.

When you’ve got any questions or feedback, take part on the discussion board dialogue under! We’re pleased to listen to from you :]