• Stars
    star
    118
  • Rank 290,547 (Top 6 %)
  • Language
    Scala
  • License
    Other
  • Created over 6 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Elm-inspired Scala library for writing web user interfaces

scalm

Join the chat at https://gitter.im/julienrf/scalm

Elm-inspired Scala library for writing web user interfaces.

Installation

scalm supports Scala 2.12 and Scala.js 0.6.

Since scalm uses a JavaScript library (snabbdom) under the hood, you will have to use scalajs-bundler:

// project/plugins.sbt
addSbtPlugin("ch.epfl.scala" % "sbt-scalajs-bundler" % "0.9.0")
// build.sbt
enablePlugins(ScalaJSBundlerPlugin)
libraryDependencies += "org.julienrf" %%% "scalm" % "1.0.0-RC1"

Overview

Elm Architecture

Scalm provides a runtime environment for executing applications designed according to the Elm architecture.

In essence, the state of the application is modeled by an immutable Model, events that change the state of the application are modeled by an immutable Msg type, state transitions are implemented by a (Msg, Model) => Model function, and finally, a Model => Html[Msg] function defines how to render the state of the application in HTML.

Reacting to User Input

Here is how the usual counter example looks like with scalm:

import scalm.{Html, Scalm}
import scalm.Html._
import org.scalajs.dom.document

object Counter {

  def main(): Unit = Scalm.start(document.body)(init, update, view)

  type Model = Int

  def init: Model = 0

  sealed trait Msg
  case object Increment extends Msg
  case object Decrement extends Msg

  def update(msg: Msg, model: Model): Model =
    msg match {
      case Increment => model + 1
      case Decrement => model - 1
    }

  def view(model: Model): Html[Msg] =
    div()(
      button(onClick(Decrement))(text("-")),
      div()(text(model.toString)),
      button(onClick(Increment))(text("+"))
    )

}

Dealing With Effects

In the architecture presented above, the state of the application evolves with DOM events but there is no way to perform HTTP requests or register a timer. We call this kind of actions “effects”. We classify them into two groups: commands and subscriptions. Commands let you do stuff, whereas subscriptions let you register that you are interested in something. You can find more information on effects here.

Here is how the clock example looks like in scalm:

import scalm.{App, Cmd, Html, Scalm, Sub}
import scalm.Html._
import org.scalajs.dom.document

import scalajs.js
import concurrent.duration.DurationInt

object Clock extends App {

  def main(): Unit = Scalm.start(this, document.body)

  type Model = js.Date

  def init: (Model, Cmd[Msg]) = (new js.Date(), Cmd.Empty)

  case class Msg(newTime: js.Date)

  def update(msg: Msg, model: Model): (Model, Cmd[Msg]) =
    (msg.newTime, Cmd.Empty)

  def subscriptions(model: Model): Sub[Msg] =
    Sub.every(1.second, "clock-ticks").map(Msg)

  def view(model: Model): Html[Msg] = {
    val angle = model.getMinutes() * 2 * math.Pi / 60 - math.Pi / 2
    val handX = 50 + 40 * math.cos(angle)
    val handY = 50 + 40 * math.sin(angle)
    tag("svg")(attr("viewBox", "0, 0, 100, 100"), attr("width", "300px"))(
      tag("circle")(attr("cx", "50"), attr("cy", "50"), attr("r", "45"), attr("fill", "#0B79CE"))(),
      tag("line")(attr("x1", "50"), attr("y1", "50"), attr("x2", handX.toString), attr("y2", handY.toString), attr("stroke", "#023963"))()
    )
  }

}

Discussion

To my experience, correctly implementing a user interface is hard.

The very disciplined Elm programming model helps me a lot to reason about the user interface implementation.

More specifically, in this programming model the mapping between the state of the application and the rendered HTML is easy to follow. Furthermore, commands and subscriptions simplify resource management a lot (you don’t have to worry about cancelling some event handler anymore, this is taken care of by the runtime).

On the other hand, the architecture is, by design, not extremely efficient: on each event the entire application state is recomputed. We use a virtual-dom technique to patch the DOM as efficiently as possible, but still, that’s a lot of work that’s not needed with approaches like monadic-html or Binding.scala.

More Repositories

1

play-json-derived-codecs

Scala
191
star
2

play-jsmessages

Library to compute localized messages of your Play application on client side
Scala
124
star
3

enum

Scala
68
star
4

effects-without-monads-but-with-dotty

Scala
38
star
5

chooze

Scala
19
star
6

pfe-samples

Code samples of the book Play Framework Essentials
Java
18
star
7

faithful

Lightweight Scala.js promise implementation that does not violate parametricity
Scala
18
star
8

lms-tutorial

Scala
12
star
9

play-jsonp-filter

JSONP filter for Play framework
Scala
11
star
10

mergical

Merge your iCal feeds
JavaScript
10
star
11

composite-ui-play2

Scala
8
star
12

twitterstream

Sample application inspired from the twitterstream Play 2.0 sample
Scala
7
star
13

arrows-typelevel-summit-2017

JavaScript
7
star
14

glitter

Embedded Scala DSL for HTML templates
Scala
7
star
15

play-table

Table module for Play! framework
Java
7
star
16

reactivemongo-derived-codecs

Scala
7
star
17

scala-lessons

Scala
6
star
18

play-products

Scala
6
star
19

di-with-play2

Dependency injection example using Play2
Scala
6
star
20

closely

Find useful amenities (drinking water, waste bin, pharmacy, etc.) close to you
JavaScript
5
star
21

play-macro-templates

Using Scala macros to dynamically call Play templates
Scala
5
star
22

play-custom-pathbinder

Scala
4
star
23

endpoints-problemdetailserrors

Scala
3
star
24

play-forms

Scala
2
star
25

happy-numbers

My solution to the Tony Morris “Happy Numbers” exercise
Scala
2
star
26

dotty-endpoints

Scala
2
star
27

play-table-sample

Sample application for the Play! table module
Java
2
star
28

etoffe

Lightweight markup language processor written in Scala
Scala
2
star
29

Alaska

Scala vs Haskell
Haskell
2
star
30

EquiDist

2
star
31

julienrf.github.com

HTML
2
star
32

jQuery-rant

JavaScript
2
star
33

play-endpoints

Scala
2
star
34

play-modules

Scala
1
star
35

tp-scala

Scala
1
star
36

pac-js

JavaScript
1
star
37

play-glitter-sample

Sample application for the Play! glitter module
Scala
1
star
38

blueprintr

Scala
1
star
39

resilience

TeX
1
star
40

play-plovr

Plovr integration into Play! framework 1.x
Java
1
star
41

play-glitter

Glitter module for Play! framework
Scala
1
star
42

pac-gwt

A PAC framework on top of GWT
Java
1
star
43

selector3

JavaScript
1
star
44

Debate-it

Debate platform
Python
1
star
45

tyco

Reusable components to build web sites
Scala
1
star
46

el

Reduce the boilerplate to build DOM fragments
JavaScript
1
star