This is a proof of concept to demonstrate how Laminar can be used to implement the Angular tutorial, the Tour of Heroes.
Laminar is an HTML framework made in Scala, using Scala.js, and based on the Functional Reactive Programming (FRP) principles.
In one word, the goal of FRP is to free you from callbacks, "replacing" them with variables and streams.
The goal is to demonstrate the capabilities of Laminar, as well as a some kind of tutorial.
We are not an expert in Angular, nor in Laminar, for that matter, so we're going to follow the tour of heroes, and implement it as we go.
This is the name of the Angular tutorial. The goal is to build a small application involving displaying information about some heroes, modify them...
As said above, we are gonna implement the tutorial as we go, without knowing what comes ahead. In particular, this means that there might be better ways of doing things that we do. Furthermore, we do not "prepare the ground" for the future when we find something new.
Every part of the Tour of Heroes will be put in a commit, so you can follow the commit history if you like.
Laminar builds a layer of ReactiveElement
s on top the the
usual HTML DOM. This layer enhances the DOM with the FRP
principles, allowing for powerful, concise and robust DOM
manipulation.
Angular, for its part, is base on so-called components. A Component is a kind of super-DOM-element with a rich inner HTML structure, defined in some adjacent HTML file.
In here, Components are a trait Component[T]
, where T
is
a DOM type. As for Angular component, you can create a rich
HTML structure. The difference is that this structure is build
through Laminar, in Scala, which is more robust and more
customizable.
Components can be easily inserted within the default Laminar reactive elements via implicit conversion.
In here, every component will live in its own Scala
package, within the components
package.
It's quite easy. Make sure you have
sbt
installed. Within it, execute the fastOptJS
command, and
open the html/index.html
file in any browser.
We decided to use ScalaTags for doing CSS. ScalaTags allows for making type-safe CSS style-sheet within the Scala code, and it generates for us the desired CSS code.
In order to make component-specific style, the way we
do it is to make a StyleSheet
or
CascadingStyleSheet
object
in the same package as
the component. This object
can for example be
package-private, so that it is only available for
its component. Then, the cls
reactive attribute
of the elements can be set as the name
property
of the ScalaTags CSS classes.
The generated CSS needs to be inserted in a
<style>
element in the head of the document. This
is done automatically for you if you extend
ComponentStyleSheet
or
CascadingComponentStyleSheet
.
Here we make a simple component Foo
that displays
a <span>
with red background colour. This background
colour will come from a CSS class.
In FooStyles.scala
:
package components.foo
import components.css.CascadingComponentStyleSheet
import scalatags.Text.all._
private[foo] object FooStyles extends CascadingComponentStyleSheet {
initStyleSheet()
val redBG = cls(backgroundColor := "red")
}
In Foo.scala
:
package components.foo
import com.raquo.laminar.api.L._
import com.raquo.laminar.nodes.ReactiveElement
import components.Component
import org.scalajs.dom
final class Foo extends Component[dom.html.Span] {
val rel: ReactiveElement[dom.html.Span] =
span(cls := FooStyles.redBG.name, "Hello")
}
As any Scala application, the entry point is some main
method of a top level object
. In this case, you'll find
it at src/main/scala/main/LaminarTourOfHeroes
. In here,
it mainly renders the top component, called appComponent
.