![](/style/images/good.png)
![](/style/images/bad.png)
Introduction to Scala.js
source link: https://blog.knoldus.com/introduction-to-scala-js/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Scala.js
A safer way to build robust front-end web applications!
In this blog, we are gonna utilizing a whole lot of features of Scala to build a simple front-end application using Scala.js.
So, let’s get it started-
Step-1: – Creating an sbt project
Create a folder namedscala-js-example and inside it create a build.sbt.
build.sbt
lazy val root = project.in(file("."))
.settings(
name := "scala-js-example",
version := "0.0.1",
scalaVersion := "2.13.3")
Now, create a new folder named as a project inside the scala-js-example folder and add these three files: –
build.properties
sbt.version = 1.4.1
plugins.sbt
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.2.0")
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0")
Dependencies.scala
import org.portablescala.sbtplatformdeps.PlatformDepsPlugin.autoImport._
import sbt._
object Dependencies {
private object versions {
lazy val scalaJsDom: String = "1.1.0"
}
object js {
lazy val scalaJsDom = Def.setting("org.scala-js" %%% "scalajs-dom" % versions.scalaJsDom)
}
}
As you can see above, the Scala version for the project is 2.13.3, SBT version is 1.4.1 and to run the SBT I am using JVM-14.
The next step would be to execute sbt clean compile
For now, a basic sbt project has created, the next step would be to edit the build.sbt again.
build.sbt
import Dependencies._
import sbtcrossproject.CrossPlugin.autoImport.{crossProject => sbtCrossProject}
lazy val root = project.in(file("."))
.aggregate(crossProjectJS, crossProjectJVM)
.settings(
name := "scala-js-example",
version := "0.0.1",
scalaVersion := "2.13.4")
lazy val crossProject = sbtCrossProject(JSPlatform, JVMPlatform).in(file("."))
.settings(
version := "0.0.1",
scalaVersion := "2.13.3")
lazy val crossProjectJVM = crossProject.jvm
lazy val crossProjectJS = crossProject.js.settings(
libraryDependencies ++= Seq(js.scalaJsDom.value),
crossTarget in fastOptJS := baseDirectory.value / "src/main/resources/web/scala-js"
)
So, let’s try to understand build.sbt
We have added a cross-project plugin, to create a cross-project, this is done to better organize the code, which means, the code which will be designed to run Js Virtual machine will go inside js/src/main/scala, the code which will be designed to run Java Virtual machine will go inside jvm/src/main/scala and the common code between two of them will go inside the shared/src/main/scala.
For more info on cross-project, please visit: – https://www.scala-js.org/doc/project/cross-build.html
So, the project structure will gonna look like
scala-js-example
+- jvm
| +- src/main/scala
| +- app
| +- Main.scala
+- js
| +- src/main/resources
| +- web
| +- css
| +- main.css
| +- scala-js
| +- index.html
| +- src/main/scala
| +- handler
| +- ContainerEventHandler.scala
| +- WindowEventHandler.scala
| +- css
| +- classes
| +- package.scala
+- shared
| +- src/main/resources
| +- src/main/scala
| +- logger
| +- Logger.scala
+- project
| +- build.properties
| +- Dependencies.scala
| +- plugins.sbt
+- build.sbt
Now, if you notice we have something like this inside build.sbt
crossTarget in fastOptJS := baseDirectory.value / "src/main/resources/web/scala-js"
This piece of block says to generate the resultant Js file inside js/src/main/resources/web/scala-js and from there we would be using this Js file to our HTML code.
The project structure is created now and let’s move towards the code
Step-2: – Writing scala code
src\main\scala\app\Main.scala
package app
import com.knoldus.logger.Logger
/**
* Main from jvm.
*/
object Main extends App {
val message = "SCALA-JS-EXAMPLE"
Logger.info(message)
}
src\main\scala\handler\ContainerEventHandler.scala
package handler
import css.classes._
import com.knoldus.logger.Logger
import org.scalajs.dom._
import scala.scalajs.js.annotation.JSExportTopLevel
/**
* This event handler will handle events generated from `container`.
*
* Note:- `container` is the id assigned to `div` element inside `src\main\resources\web\index.html`.
*/
object ContainerEventHandler {
@JSExportTopLevel("handleContainerButtonClickEvent")
def handleButtonClickEvent(): Unit = {
val bodyClassList = document.querySelector("body").classList
bodyClassList.toggle(LINER_GRADIENT_DESIGN_BOTTOM_LEFT)
bodyClassList.toggle(LINER_GRADIENT_DESIGN_TOP_RIGHT)
Logger.info("Gradient designed changed")
}
}
src\main\scala\handler\WindowEventHandler.scala
package handler
import css.classes._
import com.knoldus.logger.Logger
import org.scalajs.dom._
import scala.scalajs.js.annotation.JSExportTopLevel
/**
* This Event handler will handle events from `window` object.
* Ex:- window.onload = onLoadHandler
*/
object WindowEventHandler {
@JSExportTopLevel("onLoadHandler")
def onLoadHandler(): Unit = {
val webPageLoadedMessage = "Web page loaded successfully."
window.alert(webPageLoadedMessage)
document.querySelector("#container").classList.remove(DISPLAY_NONE)
Logger.info(webPageLoadedMessage)
}
}
src\main\scala\css\classes\package.scala
package css
/**
* This object contains all name of the global css classes present inside
* `src\main\resources\web\css\main.css`.
*/
package object classes {
lazy val DISPLAY_NONE: String = "display-none"
lazy val LINER_GRADIENT_DESIGN_BOTTOM_LEFT: String = "linear-gradient-design-bottom-left"
lazy val LINER_GRADIENT_DESIGN_TOP_RIGHT: String = "linear-gradient-design-top-right"
lazy val COLUMN_FLEX_CONTAINER: String = "column-flex-container"
lazy val FULL_WIDTH_HEIGHT: String = "full-width-height"
}
src\main\resources\web\css\main.css
html {
width: 100%;
height: 100%;
}
body {
overflow:hidden;
}
.linear-gradient-design-bottom-left {
background-image: linear-gradient(to bottom left, #66ffff, #ff66ff);
}
.linear-gradient-design-top-right {
background-image: linear-gradient(to top right, #66ffff, #ff66ff);
}
.display-none {
display:none
}
.column-flex-container {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.full-width-height {
width: 100%;
height: 100%;
}
#container > button {
margin: auto;
font-size: xx-large;
background-color: white;
}
src\main\resources\web\index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>scala-js-example</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body class="linear-gradient-design-bottom-left">
<div id="container" class="display-none column-flex-container full-width-height">
<h1>Welcome to <b>scala-js</b></h1>
<button onclick="handleContainerButtonClickEvent()">Click Me</button>
</div>
http://scala-js/scala-js-example-fastopt.js
<script>
window.onload = onLoadHandler
</script>
</body>
</html>
shared
src\main\scala\logger\Logger.scala
package logger
/**
* Sample Logger to log output in browser for scala-js and on console for scala-jvm.
*/
object Logger {
def info(messages: Any*): Unit = println(messages.map(_.toString).mkString(","))
}
Now we are all set and let’s go ahead and run this
Step-2: – Executing the project
Steps to execute
sbt "project crossProjectJVM" run
Output
SCALA-JS-EXAMPLE
Steps to execute
sbt fastOptJS
After this, you can see that the scala-js folder inside js/src/main/resources/web will contain a Js file named scala-js-example-fastopt.js
Now let just go to your index.html file inside js/src/main/resources/web and update the src attribute of the script tag to point to the generated Js file
Like for example, as mentioned above inside index.html
http://scala-js/scala-js-example-fastopt.js
Open index.html file with a web browser and you can see that
- A alert box at start-up
- Background color change on every button click
- Open the Js console inside browser inspect and there you can see the output of
println
.
Hope this blog helps you to understand the basic concepts of Scala.js.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK