はじめに
Elm + PlayFramewark(Scala)をやりたくて、無理矢理ぶっ込んだ話です。
諸々やり方に不備があるかと思いますが、ご了承を。
開発環境
OS: macOS Mojave
Editer: Vim
・言語
Elm 0.19.0
Scala 2.12.8
sbt 1.2.8
PlayFrameworkのアプリを作成
今回は、sbt経由で作成する。
言語は、Scalaで作成する。
$ cd ~
$ sbt new playframework/play-scala-seed.g8
[info] Set current project to play (in build file:/Users/yanagawamasakazu/play/)
[info] Set current project to play (in build file:/Users/yanagawamasakazu/play/)
This template generates a Play Scala project
name [play-scala-seed]: elm
organization [com.example]: com.play.masa
Template applied in /Users/yanagawamasakazu/play/./elm
PlayFrameworkアプリに、Elmをぶっ込む。
最初は、sbt-elmでの導入を検討したが、結局、app
フォルダ内にassets
フォルダを作成し、その中にelm
フォルダを作成して、elm
内でelm init
を実行した。
$ cd elm
$ mkdir app/assets
$ mkdir app/assets/elm
$ cd app/assets/elm
$ elm init
その後、elm init
で生成されたsrc
フォルダ内で、Main.elm
を作成し、以下を記入。
module Main exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
main : Html msg
main = h1 [][text "Hello Elm!"]
その後、ターミナルで以下のコマンドを実行する。
$ elm make src/Main.elm --output=elm.js
気をつけたいのは、elm.jsを生成し、出力している所だ。
Viewに反映させる。
まず、app/views/main.scala.html
を以下のように編集する。
@*
* This template is called from the `index` template. This template
* handles the rendering of the page header and body tags. It takes
* two arguments, a `String` for the title of the page and an `Html`
* object to insert into the body of the page.
*@
@(title: String)(content: Html)
<!DOCTYPE html>
<html lang="en">
<head>
@* Here's where we render the page title `String`. *@
<title>@title</title>
<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
<!-- 追加した所 -->
<script src="@routes.Assets.versioned("elm/elm.js")" type="text/javascript"></script>
</head>
<body>
@* And here's where we render the `Html` object containing
* the page content. *@
@content
<script src="@routes.Assets.versioned("javascripts/main.js")" type="text/javascript"></script>
</body>
</html>
次に、app/views/index.scala.html
を以下のように編集する。
@()
@main("Welcome to Elm") {
<div id="app"></div>
<script type="text/javascript">
Elm.Main.init({
node: document.getElementById("app")
});
</script>
}
最後に、~/elm
に戻って、PlayFrameworkアプリのサーバを起動する。
$ sbt run
localhost:9000
にアクセスすると、「Hello Elm!」が表示される。
Controllerから、変数をElmに渡して表示する。
今度は、HomeController.scala
から変数をElmに渡して、Viewに表示させる。
まずは、HomeController.scala
のdef index
を編集する。
def index() = Action { implicit request: Request[AnyContent] =>
val msg = "Hello, Scala!";
Ok(views.html.index(msg))
}
Scalaから渡された変数をElmに反映するには、Elmのflags
という機能を使う。
まず、index.scala.html
を以下のように編集する。
@(msg: String)
@main("Welcome to Elm") {
<div id="app"></div>
<script type="text/javascript">
Elm.Main.init({
node: document.getElementById("app"),
flags: `@msg`
});
</script>
}
続いて、Main.elmを以下のように編集する。
module Main exposing (..)
import Browser
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.Attributes exposing (..)
import Http
import Html.Events exposing(..)
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
init : String -> ( Model, Cmd msg )
init flags =
( { msg = flags }, Cmd.none )
type alias Model =
{ msg : String }
type Msg
= NoMessage
update : Msg -> Model -> ( Model, Cmd msg)
update msg model =
( model, Cmd.none)
view : Model -> Html Msg
view model =
div [][
h1 [][ text "Hello Elm!"]
,h1 [][ text model.msg ]
]
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
再度、app/assets/elm
フォルダ内でelm make src/Main.elm --output=elm.js
を実行した後、サーバを起動する。
すると、以下のように表示される。
感想
なんとか、Elm + Playframework(Scala)導入できました。
ただ、flags
の仕様が、まだ把握しきれてないので、
色々試してみたいですね。