A Scala.js tutorial: “Hello, world” with an HTML button click

In my first “Hello, world” Scala.js tutorial I showed how to get started with Scala.js, including some necessary setup/configuration work. That tutorial ended by showing how to get the string “Hello, world” displayed in a browser.

In this tutorial I’ll take this a little further and show how to create an HTML button you can click that results in the string “Hello, world” being displayed in a JavaScript alert window. When the button is clicked, the alert window will be displayed by your Scala/Scala.js code.

July, 2020 Update: I don’t have time to update this page, but please see the end of this article for the latest, greatest source code. In short, several dependencies and versions have changed since I originally wrote this.

1. Create a new HTML page

The first step in this process is to create a new HTML web page. Name this file hello2.html, and place it in the root directory of your project with these contents:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Scala.js, Hello World 2</title>
</head>
<body>
    <button type="button" id="hello-button">
        Click me!
    </button>

    <!-- important that jsdeps is first -->
    <script type="text/javascript" src="./target/scala-2.12/scala-js-hello-world-jsdeps.js"></script>
    <script type="text/javascript" src="./target/scala-2.12/scala-js-hello-world-fastopt.js"></script>

</body>
</html>

The important changes to this file compared to hello1.html are:

  • This page has a new <button> element.
  • This page includes a new file named scala-js-hello-world-jsdeps.js. As the name jsdeps implies, this file will contain dependencies for our code, specifically dependencies that the scala-js-hello-world-fastopt.js will rely on. You’ll learn more about these dependencies in a few moments.

2. Make updates to use jQuery

After a little experimentation, it seems that the easiest way to handle an HTML button click from Scala.js code is to use a Scala.js jQuery facade library along with Scala.js. To do this we’ll add one of these libraries to our project. To do this, add this line to your build.sbt file:

libraryDependencies += "org.querki" %%% "jquery-facade" % "1.2"

This lets us use the jquery-facade library in our project. This library is used in the scala-js.org Basic Tutorial, so I used it. (More on this later.) As before, notice that this dependency line uses three percent symbols:

libraryDependencies += "org.querki" %%% "jquery-facade" % "1.2"
                                    ---

As mentioned previously, in “normal” Scala projects you use %% to include libraries, but you use %%% to include Scala.js libraries in Scala.js projects.

That code brings the jquery-facade library into our project (written in Scala), and now we also need to include the actual jQuery library (written in JavaScript) into our HTML file. We could just include a line of code like this into our HTML file:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>

But, SBT gives us another way to bring the jQuery JavaScript library into our project. To use the SBT approach, add these two lines to your build.sbt file:

skip in packageJSDependencies := false
jsDependencies += "org.webjars" % "jquery" % "2.2.1" / "jquery.js" minified "jquery.min.js"

These lines let us use the WebJars “client-side web libraries as packaged JAR files” in our project. In short, these lines bring in version 2.2.1 of the jQuery JavaScript library (the actual JavaScript library, not the facade), and then when you run fastOptJS, that JavaScript code is written to the local target/scala-2.12/scala-js-hello-world-jsdeps.js file. This step isn’t necessary — you can include jQuery using the <script> tag as shown previously — but it seems to be preferred as a way of dependency management, so I’ll use it in this example. At the very least it shows how to add JavaScript libraries/dependencies to Scala.js/SBT projects.

At this point, these two lines in the hello2.html file should now make sense:

<!-- important that jsdeps is first -->
<script type="text/javascript" src="./target/scala-2.12/scala-js-hello-world-jsdeps.js"></script>
<script type="text/javascript" src="./target/scala-2.12/scala-js-hello-world-fastopt.js"></script>

The first line brings our JavaScript dependencies into our HTML file (iQuery, in this case), and the second line contains the JavaScript version of the custom Scala.js code we’ve written.

As a final note, because the Scala code we’re about to write depends on the jQuery dependency, the “jsdeps” file also needs to come first in this list.

3. The new Scala code

Now that (a) we have the new HTML file and (b) jQuery is ready to be used in our project, the main thing that’s left to do is write some Scala/Scala.js code to respond to the <button> click. Before doing this, an important point to notice is that the <button> in hello2.html has an id of hello-button:

<button type="button" id="hello-button">
                          ------------

We’ll refer to this id in the Scala code that follows.

Once you figure out what code to import, the Scala code to respond to a button click and display a JavaScript window with the jQuery facade library is surprisingly simple:

import org.scalajs.dom
import org.querki.jquery._

object Hello2 {

    def main(args: Array[String]): Unit = {

        // handle the login button click
        $("#hello-button").click{() =>
            dom.window.alert("Hello, world")
        }
    }

}

If you’ve used jQuery before that code should look very familiar. It can be read as, “Find the HTML element with the id hello-button, and when it’s clicked, run this little algorithm to display a JavaScript alert window with the text Hello, world.” It’s nice that you can use the $ symbol in your Scala code, because that’s consistent with using jQuery in JavaScript.

4. Setting the main class

Before running this example you need to do one more thing: Make a change to build.sbt to account for the fact that we now have two main methods in our project — one in Hello1.scala and a new one in Hello2.scala. To do this, add this line to your build.sbt file, just below the scalaJSUseMainModuleInitializer setting:

mainClass in Compile := Some("hello.Hello2")

At this point your complete build.sbt file should look like this:

name := "Scala.js Hello World"
version := "1.0"
scalaVersion := "2.12.8"                      // or any other Scala version >= 2.10.2

// ScalaJS
scalaJSUseMainModuleInitializer := true       // this is an application with a main method
mainClass in Compile := Some("hello.Hello2")  // start with the `main` in Hello2
enablePlugins(ScalaJSPlugin)

// DOM
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.9.7"

// jQuery
libraryDependencies += "org.querki" %%% "jquery-facade" % "1.2"
skip in packageJSDependencies := false
jsDependencies += "org.webjars" % "jquery" % "2.2.1" / "jquery.js" minified "jquery.min.js"

5. Running this example

Now you’re ready to run this example. Assuming that you’re still in the SBT console, you’ll need to run the reload command to read the changes you made to build.sbt:

sbt> reload

After that you could run the fastOptJS command, but a cooler solution is to run it like this:

sbt> ~fastOptJS

Just like continuously compiling your code with ~compile or testing it with ~test, this command tells SBT to watch the files in your project and re-run the fastOptJS command any time a source code file changes. When you first issue this command you should see some output like this:

1. Waiting for source changes in project scalajshelloworld... (press enter to interrupt)
[info] Compiling 1 Scala source to target/scala-2.12/classes ...
[info] Done compiling.
[info] Fast optimizing target/scala-2.12/scala-js-hello-world-fastopt.js
[success] Total time: 1 s, completed Jun 14, 2019 5:55:50 PM
2. Waiting for source changes in project scalajshelloworld... (press enter to interrupt)

Now open the hello2.html file in your browser. On macOS you can do this with the open hello2.html command, or you can open the file with a URL that will be something like file:///Users/al/ScalaStuff/ScalaJSHelloWorld/hello2.html. When the file opens in your browser you should see a “Click me” button like this:

Scala.js - Hello, world button

When you click that button you should then see this result:

Scala.js - Hello, world button clicked, JavaScript alert window

Congratulations, you have just written some Scala.js code to respond to an HTML button click, thanks to Scala, SBT, Scala.js, jQuery, and the jQuery facade library (and the Scala.JS DOM library, Node.js, ...).

Discussion

I should note that the Scala.js jQuery facade library I used in this example hasn’t been updated in two years. I used it because it was used in the Scala.js Basic Tutorial, but a jQuery facade library that is currently maintained is udash-jquery, so it would be better to use that one.

For more information, you can find a list of other facades on the Scala.js JavaScript library facades page.

July, 2020 Update

Here’s a brief summary of the changes that have happened since I originally wrote this article. First, project/plugins.sbt:

addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.1.1")

// for adding webjars
addSbtPlugin("org.scala-js" % "sbt-jsdependencies" % "1.0.1")

Next, build.sbt:

name := "ScalaJs2"
version := "0.1"
scalaVersion := "2.13.2"

// ScalaJs
scalaJSUseMainModuleInitializer := true   // this is an application with a main method
mainClass in Compile := Some("hello.Hello2")
enablePlugins(ScalaJSPlugin)

// DOM
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "1.0.0"

// jquery/webjars
// https://github.com/scala-js/jsdependencies
// note that you need to update project/plugins.sbt for this to work
enablePlugins(JSDependenciesPlugin)
libraryDependencies += "org.querki" %%% "jquery-facade" % "2.0"
jsDependencies += "org.webjars" % "jquery" % "2.1.4" / "2.1.4/jquery.js"

hello2.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Scala.js, Hello World 2</title>
</head>
<body>
    <button type="button" id="hello-button">
        Click me!
    </button>

    <!-- important that jsdeps is first -->
    <script type="text/javascript" src="./target/scala-2.13/scalajs2-jsdeps.js"></script>
    <script type="text/javascript" src="./target/scala-2.13/scalajs2-fastopt.js"></script>
</body>
</html>

Finally, Hello2.scala, which stays the same:

package hello

import org.scalajs.dom
import org.querki.jquery._

object Hello2 {

    def main(args: Array[String]): Unit = {
        // handle the login button click
        $("#hello-button").click{() =>
            dom.window.alert("Hello, world")
        }
    }

}

Those are the latest changes and versions as of July 28, 2020.

Summary

In this Scala.js tutorial you saw how to respond to a user clicking an HTML <button> by using jQuery and a jQuery facade library in your Scala.js code. If anything in this tutorial doesn’t make sense, I encourage you to go back and read my first Scala.js “Hello, world” tutorial. It can also help to read the scala-js.org Basic Tutorial. (That tutorial also shows another way to handle an HTML button click.)

In the next tutorial I’ll demonstrate how to get started writing a single-page web app using Scala.js. In that tutorial the body of the new HTML page will basically only contain these contents:

<body>
    <div id="root"></div>          
</body>

Reporting live today from Broomfield, Colorado, this is Alvin Alexander.