Elm0.19でCSSフレームワーク”Bulma”を試してみる(4)ハンバーガーメニュー
以前、Vue.jsを触っていた時に、以下の記事がわかりやすくて感動しました。
https://qiita.com/isamusuzuki/items/5ec800e423a3a56ef03d
Vue.jsには、状態管理の方法としてvuexというものがあります。
この絵は、ElmのMODEL,UPDATE,VIEWと全く同じです。
なので、真似してみたいと思います。
今回やりたいこと
- ElmのSPA(SinglePageApplication)にBulmaを組み込む
- Bulmaのレスポンシブなハンバーガーメニューを実装する
ソースコード
https://github.com/adash333/elm-bulma-hamburger
DEMOサイト
https://laughing-jepsen-024a72.netlify.com/
開発環境
Windows 10 Pro
Chrome
VisualStudioCode 1.32.3
git version 2.20.1.windows.1
nvm 1.1.7
node 10.2.0
npm 6.4.1
elm 0.19.0-bugfix6
elm-format 0.8.1
VisualStudioCodeの拡張機能でelmをインストールして、settings.jsonに以下のようにelmを設定。
(『Alt + Shift + F』と『Ctrl + S』を使用。)
"[elm]": {
"editor.formatOnSave": true
},
新規Elmアプリの作成
C:/elm/ フォルダに、elm-bulma-hamburger/ フォルダを作成し、VisualStudioCodeで開き、Ctrl+@でコマンドプロンプトを開き、以下を入力します。
途中で何か聞かれたらEnterを押します。
elm/url パッケージもインストールしておきます。
elm init
elm install elm/url
ElmでBulmaを使用し、Netlifyにデプロイするための準備
Browser.applicationからbulmaを使用し、Netlifyにデプロイするための以下の3つのファイル(index.html, .gitignore, netlify.toml)をコピペします。
src/Main.elmの新規作成
以下のソースコードをほぼコピペします。
参考:Elmで複数ページからなる極簡単なSPA(シングルページアプリケーション)を作成(ソースコードあり)
https://github.com/adash333/elm-navigation2/blob/master/src/Main.elm
また、いらすとやから画像を3つダウンロードして、img/フォルダに保存します。
ここで一度、elm-liveで開発サーバで表示してみます。
elm-live src/Main.elm --open -- --output=main.js
ここまでのコードを、GitHubへpushします。
https://github.com/ にログインして、新規リポジトリを作成します。
今回は、リポジトリの名前は elm-bulma-hamburger としました。
Ctrl+C => y + Enterでサーバを停止してから以下を入力して、GitHubへpushします。
git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/adash333/elm-bulma-hamburger.git
git push -u origin master
この時点でのソースコード
https://github.com/adash333/elm-bulma-hamburger/tree/896743d790e42fd22aa53d95de1106cac7bb2d0c
AboutページとContactページの上の部分を編集
elm-live src/Main.elm –open — –output=main.js で見ながら、少し見栄えを変更します。
case model.url.path of
"/" ->
div [] []
"/about" ->
section [ class "hero is-primary is-bold" ]
[ div [ class "hero-body" ]
[ div [ class "container" ]
[ h1 [ class "title is-size-2" ] [ text "About" ]
, h2 [ class "subtitle is-size-4" ] [ text "EBHとは?" ]
]
]
]
"/contact" ->
section [ class "hero is-info is-bold" ]
[ div [ class "hero-body" ]
[ div [ class "container" ]
[ h1 [ class "title is-size-2" ] [ text "Contact" ]
, h2 [ class "subtitle is-size-4" ] [ text "お問い合わせ" ]
]
]
]
_ ->
div [] []
ナビゲーションバーをVIEWに記載する
こちらのコードを参考に、HTML to ELMのを使いつつ、VIEWにナビゲーションバーのコードの一部を記載してみます。
nav [ attribute "aria-label" "main navigation", class "navbar is-white", attribute "role" "navigation" ]
[ div [ class "navbar-brand" ]
[ div [ class "navbar-item" ]
[ text "EBH" ]
, div [ class "navbar-burger", attribute "data-target" "navMenu" ]
[ span []
[]
, span []
[]
, span []
[]
]
]
, div [ class "navbar-menu", id "navMenu" ]
[ div [ class "navbar-end" ]
[ a [ class "navbar-item", href "/" ]
[ text "トップ" ]
, a [ class "navbar-item", href "/about" ]
[ text "NBHとは?" ]
, a [ class "navbar-item", href "/contact" ]
[ text "お問い合わせ" ]
]
]
, text " "
]
一応、レスポンシブになっています。ちょっとだけ、それっぽくなってきました。
HTML to ELM が必須でした。
attribute “aria-label" “main navigation"
という書き方は 、TML to ELM を使わなければ、たどり着けませんでした。
ここまでのソースコード
https://github.com/adash333/elm-bulma-hamburger/tree/09f094e692115dd44726700e7a972dc505dabc91
ハンバーガーメニューをトグルさせる
横幅が狭いときに、ナビゲーションバーの右端に出てくる3本線の『ハンバーガーメニュー』をクリックすると、ナビゲーションメニューが縦に広がって表示されるようにします。
参考:ハンバーガーメニューをトグルさせる
Vue.jsでの、
@click="toggleMenu" :class="{'is-active’: isMenuActive}"
の、@click は onClick でよいと思うのですが、
:class を、elmでどのように記載したらよいでしょうか?
参考: Vue.jsのv-bind:class について
https://jp.vuejs.org/v2/guide/class-and-style.html
elmの場合は、modelに isMenuActive: Bool を定義して、case model.isMenuActive of のTrueとFalseで場合分けして記載する感じでしょうか?それともif then elseでもいけるでしょうか?
参考:https://github.com/ababup1192/elm-spa-example/blob/master/src/Main.elm
試しにMODEL、UPDATE、VIEWを以下のように変更してみます。
(変更前)
-- MODEL
type alias Model =
{ key : Nav.Key
, url : Url.Url
}
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
( Model key url, Cmd.none )
-- UPDATE
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
LinkClicked urlRequest ->
(省略)
UrlChanged url ->
(省略)
-- VIEW
div [ class "navbar-burger", attribute "data-target" "navMenu" ]
div [ class "navbar-menu", id "navMenu" ]
(変更後)
import Html.Events exposing (..)
-- MODEL
type alias Model =
{ key : Nav.Key
, url : Url.Url
, isMenuActive: Bool
}
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
( Model key url (isMenuActive False), Cmd.none )
-- UPDATE
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
| ToggleMenu
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
LinkClicked urlRequest ->
(省略)
UrlChanged url ->
(省略)
ToggleMenu ->
if model.isMenuActive then ( { model | isMenuActive = False } else ( { model | isMenuActive = True }
-- VIEW
div [ class "navbar-burger", attribute "data-target" "navMenu", onClick toggleMenu, if model.isMenuActive then (class "is-active") else (class "") ]
div [ class "navbar-menu", id "navMenu", if model.isMenuActive then (class "is-active") else (class "") ]
こんな感じでいろいろ試して、修正したりしたのですが、このMODELのinitのところが一番苦労しました。
elm-liveで開発サーバで表示してみます。
elm-live src/Main.elm --open -- --output=main.js
ハンバーガーメニューのON、OFFはできるのですが、ページ遷移した後、メニューが出っぱなしになってしまいます。
ページ遷移したときにトグルが閉じるようにする
ページ遷移したとき、すなわち、リンクがクリックされたときにトグルが閉じるように(isMenuActiveがFalseになるように)します。
まず、VIEWに、リンクをクリックしたときに、ResetMenu関数を呼び出すように記載します。
VIEW(変更前)
VIEW(変更後)
次に、UPDATEに、この ResetMenu関数 を定義します。リンクをクリックしたら、isMenuActiveがFalseになるようにします。
UPDATE(変更前)
UPDATE(変更後)
elm-liveで開発サーバで表示してみます。
elm-live src/Main.elm --open -- --output=main.js
ブラウザの横幅が狭いとき、ハンバーガーメニューをクリックしてメニュー一覧を出し、リンクをクリックすると、ページ遷移とともに、メニュー一覧も閉じます。
ブラウザの横幅が広いときも特に問題なく動きました。
Netlifyにデプロイ
ターミナル画面で以下を入力して、production用のmain.jsを作成します。(今回はUglify.jsは無視します。)
elm make src/Main.elm --output=main.js --optimize
git add .
git commit -m "ToggleMenu ResetMenu"
git push
ソースコード
https://github.com/adash333/elm-bulma-hamburger
https://www.netlify.com/ にログインして、上記GitHubのリポジトリを選択して、デプロイします。設定欄は空白のままです。
無事、デプロイできたようです。
https://laughing-jepsen-024a72.netlify.com/
ディスカッション
コメント一覧
まだ、コメントがありません