PlayFramework(Scala)にElmをぶっ込む。

# はじめに
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`を作成し、以下を記入。

```elm: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`を以下のように編集する。

```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`を以下のように編集する。

```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!」が表示される。

<img width="1437" alt="スクリーンショット 2019-04-19 13.04.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154610/7c778810-2c33-776b-d92a-aab339b6ae51.png">


# Controllerから、変数をElmに渡して表示する。
今度は、`HomeController.scala`から変数をElmに渡して、Viewに表示させる。
まずは、`HomeController.scala`の`def index`を編集する。

```scala:HomeController.scala
def index() = Action { implicit request: Request[AnyContent] =>
   val msg = "Hello, Scala!";
   Ok(views.html.index(msg))
}
```

Scalaから渡された変数をElmに反映するには、Elmの`flags`という機能を使う。
まず、`index.scala.html`を以下のように編集する。

```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を以下のように編集する。

```elm: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`を実行した後、サーバを起動する。

すると、以下のように表示される。

<img width="1438" alt="スクリーンショット 2019-04-19 13.06.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154610/681ec58c-7fcb-2a21-caff-67e557677fbd.png">

# 感想
なんとか、Elm + Playframework(Scala)導入できました。
ただ、`flags`の仕様が、まだ把握しきれてないので、
色々試してみたいですね。