Elmアプリケーションの初期値をJS側から渡す。
Elmをコンパイルして出来たJSを、ElmランタイムとかElmアプリケーションと呼ぶとして、その「初期値」をJS側から設定することができます。その時に使うのがHtml.AppモジュールのprogramWithFlags関数です。
例えば、JS側から渡されたリストデータをElmで画面に表示したりとか、サーバーがElmを含んだHTMLを返すときにサーバーの値を設定しておく、といったことが出来ます。
Elm側
Elm側ではまずprogramWithFlagsを使います。
するとinit関数の引数で、JS側の値をとることができます。
module Main exposing (..) --モジュールに名前を付ける
import Html.App exposing (programWithFlags)
main =
programWithFlags {init = init , update = update , view = view ,subscriptions = subscriptions}
init : SList -> (Model,Cmd a) ---JS側から渡される値が引数に。型を書く必要がある。
init list = {data = list } ! []
JS側
JS側では、Elmを起動する際にJSオブジェクトを渡します。
..
<script type="text/javascript", src="javascripts/App.js"> //ElmをJSコンパイルして出来たJSを読み込む。
..
var app = Elm.Main.fullscreen({.....}); ---Elm.モジュール名.起動モード(データ)
fullscreen以外のモードの場合では、embed(node,データ)
、worker(データ)
とすることで渡すことが出来ます。
ElmとJSの型の対応
Elm側では、initには型を書かないといけないと書きました。port構文などJSとやりとりする部分には、型を書く必要があります。
ElmとJSの型の対応は以下のようになっています。
Elm | Javascript |
---|---|
Bool | Bool |
String | String |
Int Float | Number |
List | array |
Arrays | array |
Tuples | array(固定長、複数の型) |
Records | object |
Maybe (Nothing) | null |
Maybe (Just 42) | 42 |
Json.Encode.Value | JSON |
サーバー側のテンプレートエンジンと一緒に使う。
最後にサーバー側といっしょに使ってみます。サーバー側の値をElmアプリケーション初期値にしてみます。
以下はNode、Express、テンプレート言語jadeの例です。
index.js
var value = [{hoge:"aaaa", huga:"bbbb"}] //サーバー側の値
router.get('/', function(req, res, next) {
res.render('index', {test:value}); //testという変数でJSオブジェクトを設定しています
});
index.jade
extends layout
block content
script.
var app = Elm.Main.fullscreen( !{JSON.stringify(test).replace(/</g, '<').replace(/>/g, '>')} ); //-ここでtest変数をHTMLにレンダリング。
Elmに渡したいサーバー側の値をJSON文字列にして、それをそのままの形でHTMLに書くことでJS化する必要がありました。
上記のExpress+jadeの例では、Elmに渡したいデータをJSON.stringifyでJSON文字列にします。そのあと、文字列データ内にタグなどがあるとまずいのでreplace関数で置き換えています。そしてjadeでは!{変数}
という構文でエスケープせずに文字列をHTMLに書き込みます。
上記のjadeのやり方はセキュリティ的にどこまで安全なのかわからないですけど一番使われているみたいです。テンプレートエンジンによってHTML内のJSに渡すやり方があると思います。
以上programWithFlagsについて見ていきました。