Elmでマテリアルデザイン

#ElmでMaterial design Lite

この記事書くついでにググッてみたら最近Elmのview周りで色々出ているみたいです。

[rtfeldman/elm-css](https://github.com/rtfeldman/elm-css)
CSSをclass名とかの指定じゃなくて、Elmで作ったUnion型で指定してCSSを生成するとか。CSSのモジュール化の新しいやり方みたい。

[gdotdesign/elm-ui](https://github.com/gdotdesign/elm-ui)
Elm Architectureスタイルで使うUIライブラリ群のようです。[サイト](http://elm-ui.info/images/components.png)の説明を見るとカラーピッカーみたいなコンポーネントもあってこれはすごそう。こんなプロジェクトあったんですねぇ。。自動ビルドといったコマンドラインツールも提供しているみたいです。

[debois/elm-mdl](http://package.elm-lang.org/packages/debois/elm-mdl/latest)
GoogleのCSSフレームワークMaterial design LiteのElm用のライブラリです。JS部分をElmで書き直してたり、Elm Architectureスタイルで使えるのですけど魔改造してたりして簡単に使えるようになっています。

elm-cssとelm-uiはまだベータ版みたいです。けど速いスペースで開発が進んでいるようです。Elmのviewまわりだいぶすごいことになってきてるみたいです。

この記事ではdebois/elm-mdlライブラリを少し使ってみたのでその説明になります。


##debois/elm-mdl

debois/elm-mdlはGoogleのCSSフレームワークMaterial design LiteのElmライブラリです。
Elmのコンポーネント再利用の成功例の一つで、「Elm、elm-mdl、Phoenix」で書いてみたらよかったぞ、みたいな書き込みをよくみます。（現状リッチなCSSフレームワークがこれしかないというのもあると思う。）特徴としてElm Architectureスタイルで使うのですけど、すこし変わったインターフェースになっています。

[ライブデモ](https://debois.github.io/elm-mdl/)のページがあってドキュメントと作例が充実しています。
このページのオススメの見方は、タブごとに機能のデモになっていて、デモ毎に右の欄にデモのソースコードへのリンク、パッケージドキュメントへのリンクがあるので、デモをみてどうやって使えばこうなるのだろうなぁ、と思ったら右の欄をクリックすればわかるようになってます。


###使うには

まずインストールします。

```bash
elm-package install debois/elm-mdl -y
```

次にプロジェクトに合ったMaterial design LiteのCSSと、Webフォントと、MaterialアイコンをHTMLにリンクする必要があります。
Material design Liteの公式サイト[Material Design Lite](https://getmdl.io/started/index.html)にCDNのアドレスやCSSファイル等があります。

elm-mdlの[ライブデモ](https://github.com/debois/elm-mdl/blob/master/demo/page.html)は以下のようになっています。

```html
<link href='https://fonts.googleapis.com/css?family=Roboto:400,300,500|Roboto+Mono|Roboto+Condensed:400,700&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.2.0/material.teal-red.min.css" />
```

一番上がGoogle Webフォントのリンク
二番目がマテリアルアイコンのリンク
三番目がMaterial design LiteのCSSへのリンクです

（Google WebフォントのリンクはMaterial design Lite公式の方の例では指定してないので、必須ということではないかも。）

Material design Liteには色が全部入ったものと、カラースキーマという二色の色を指定したものがあるようです。
Material designのCSSのアドレスを見るとmaterial.主色-アクセント色.min.cssとなっています。

サイトに配置するときは軽量な二色の方を配置する必要があります。公式サイトに二色を選ぶとダウンロードリンクが出るページがあるので、そこで選びます。[Material Design Lite](https://getmdl.io/customize/index.html)

とりあえずは上記の三行をHTMLのヘッダにコピペすると動きます。

>**メモ** さらにelm-mdlのデモをみると、DialogsやEvent.focusinといった要素がChrome以外でも動くようにpolyfillをインストールしているようです。elm-mdlの機能をすべて使うときは検討したほうがいいと思われます。

これでインストールは完了です。次はElmコードの用意です。

###Elmコードでの準備

Elm Architectureで書かれた、helloとしか表示しないElm0.17コードが以下になります。

```elm
module Main exposing(..)

import Html exposing (text)
import Html.App exposing(program)

main = program {init = init , update = update , view = view ,subscriptions = subscriptions}

init = "" ! []
update msg model = model ! []
view model = text "hello"
subscriptions model = Sub.none
```

これにelm-mdlを呼び出すコードを書き足していきます。

import部分に以下のように。

```elm
import Material
import Material.Button as Button
import Material.Options as Options exposing (css)
```

ModelにMaterial.Model全体用の状態(Material.Model)をmdlという名前で設置します。

```elm
type alias Model = { mdl : Material.Model }

init : ( Model,Cmd a )
init = { mdl = Material.model } ! []
```

MsgにMdl全体用のMsgを定義します。

```elm
type Msg = Mdl ((Material.Msg Msg))
```

updateに以下略

```elm
update msg model =
    case msg of
        Mdl msg' -> Material.update msg' model

```

以上でelm-mdlを呼び出して何もしないボイラープレート的なコードが以下のようになります。


```elm
module Main exposing(..)

import Html exposing (text)
import Html.App exposing(program)
import Html.Attributes exposing (href, class, style)

import Material
import Material.Scheme
import Material.Button as Button
import Material.Options as Options exposing (css)

main = program {init = init , update = update , view = view ,subscriptions = subscriptions}

type alias Model = {mdl :Material.Model }
type Msg = Mdl ((Material.Msg Msg))

init : (Model,Cmd a)
init = {mdl = Material.model } ! []

update msg model =
    case msg of
        Mdl msg' -> Material.update msg' model

view model = text "hello"
subscriptions model = Sub.none
```

###elm-mdl書いてみる。

ここまでが準備で、あとはデモの説明を見ながら書いていくだけです。

Listを使ってみました。

```elm
import Material.List as Lists

view model =
  Lists.ul []
    <| List.indexedMap element model.data

element index data =
     Lists.li [Lists.withBody]                               
              [ Lists.content [] [ text data.supplier
                                 , Lists.body [] [ text data.address ] ]
              ]
```

Listだと、viewに種類を指定して書くだけです。

次に、型の話になりますが、cssの付け足しや、普通のHTMLを混ぜるときは、Materialの型に合わせて変換などをする必要があります。変換やUtil関数が、Material.Optionsにあります。
。

```elm
import Material.Options as Options exposing (css)

wrapCss =
    [ css "position" "fixed"
    , css "width" "100%"
    ]


allWrap model =
    Options.div
        wrapCss
        [ allView model ]
```

選択すると浮き上がる動くなどの動きがあるものは以下のような感じの書式になっています。

```
... model =
    {要素}.render Mdl    -- Msgで設定したMdl
        [ n , ..]        -- インデックス。どのパーツかの判断用
        model.mdl        -- modelで設定したmdlを渡す
        [ ...            -- Optionを付ける。cssとかイベントとかをつけたり、要素毎の設定がある。
        , ...
        , ... ]           
        [ ..             -- 子要素。Titleなど要素毎に決まった入れるものがあったりする。
        , ..
        ]
        ...
```

Tabなら以下のような感じになります。

```
import Material.Tabs as Tabs

menuTab model =
    Tabs.render Mdl
        [ 5, 2 ]
        model.mdl
        [ Tabs.ripple
        , Tabs.onSelectTab SetTab
        , Tabs.activeTab model.tab
        ]
        [ Tabs.label [] [ text "basic" ]
        , Tabs.label [] [ text "" ]
        ]
        [ heroParaTable model ]

```