Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[Elm] Attributes.batch で Attributes をもっと柔軟に使いこなそう

More than 1 year has passed since last update.

ElmでViewの共通化をしたいとき、別にViewを頑張ってつくらなくてもAttributeを"Mixin"として使い回せばいいことがわりとあります。

たとえば

module Mixin exposing (..)

import Html exposing (Attribute)
import Html.Attributes as Attributes

bigButton : Attribute msg
bigButton =
    Attributes.class "button button_big"

のような関数を定義して使いまわすイメージです。

この例は簡単なので別にこれでもいいんですが、場合によっては複数の Attribute をセットにして使いまわしたいことがしばしばあります。

module Mixin exposing (..)

import Html exposing (Attribute)
import Html.Attributes as Attributes

submitButton : Bool -> List (Attribute msg)
submitButton sending =
    [ Attributes.class "button"
    , Attributes.class "button_submit"
    , Attributes.disabled sending
    ]

このようにリストにするだけなのですが、これをViewで呼ぼうとするとどうなるでしょうか?

module Main exposing (..)

import Html exposing (Html)
import Html.Attributes as Attributes
import Mixin

submitButton : Model -> Html msg
submitButton model =
    Html.button
        (Mixin.submitButton model.sending)
        []

これを見る限りは特に問題なさそうですね!

じゃあ、Mixin.bigButtonMixin.submitButton を同時に使いたい時はどうなるでしょうか?

bigSubmitButton : Model -> Html msg
bigSubmitButton model =
    Html.button
        ( Mixin.bigButton :: Mixin.submitButton model.sending)
        []

ちょっと嫌な予感がしてきましたね?

じゃあ、ピンク色の大きな送信ボタンを作ろうと思ったらどうなるでしょうか?
ピンク色のボタンにするための Mixin が以下の型をしているとします。

pinkButton : List (Attribute msg)

こうなりますね?

bigPinkSubmitButton : Model -> Html msg
bigPinkSubmitButton model =
    Html.button
        ( Mixin.bigButton :: Mixin.submitButton model.sending ++ Mixin.pinkButton)
        []

わーお。

それじゃあ今度は、model.brokenTrue のときのみ class="broken" を付けてボタンがぶっ壊れるようにしてみましょう!

bigPinkHotSubmitButton : Model -> Html msg
bigPinkHotSubmitButton model =
    Html.button
        (Mixin.bigButton
            :: Mixin.submitButton model.sending
            ++ Mixin.pinkButton
            ++ (if model.broken then
                    [ Attributes.class "broken"
                    ]

                else
                    []
               )
        )
        []

うぅううううううああああああああ!!!!!
もういやだぁあああああああああ!!!!!!!!!!
おうちにかえるぅうううううううう!!!!!!!!!!!

sakuraaaaa.jpeg

追記 2019/8/11

最近は elm-mixin というライブラリを作ったので、そちらをメインに使っています。

Attributes.batch で解決する

たとえばこれを以下のように書けるとしたらいかがでしょうか?

module Mixin exposing (..)

...
...

submitButton : Bool -> Attribute msg
submitButton sending =
    Attributes.batch
        [ Attributes.class "button"
        , Attributes.class "button_submit"
        , Attributes.disabled sending
        ]

pinkButton : Attribute msg
pinkButton =
    Attributes.batch
        [ ...
        , ...
        ]
module Main exposing (..)

...
...

bigPinkHotSubmitButton : Model -> Html msg
bigPinkHotSubmitButton model =
    Html.button
        [ Mixin.bigButton
        , Mixin.submitButton model.sending
        , Mixin.pinkButton
        , if model.broken then
            Attributes.class "broken"

          else
            Attributes.none
        ]
        []

めちゃくちゃ可読性が向上してませんか?

これを実現する上でポイントとなっているのが次の2つの関数です。

Html.Attributes.batch : List (Attribute msg) -> Attribute msg

Html.Attributes.none : Attribute msg

ちょうど Cmd とか Sub とかの Cmd.batch Cmd.none と似たイメージですね!

arowM/html

さて、便利さはわかりましたが、残念ながらこれらの関数は elm/html にも elm-community/html-extra にも含まれていません。
これらを使うには arowM/html乗り換える 必要があります。

詳細は省きますが、elm/html加えて 他のライブラリを読み込む形では Html.Attributes.batch のようなものは実現できません。
そこで、arowM/htmlelm/html置き換える という戦略をとっています。

もちろん互換性は保ってありますので、今まで書いてきた elm/html に依存したコードは arowM/html に乗り換えてもそのまま同じように動きます。
それに加えて、上記の batchnone が使えるようになるのです。

arowM/html への置き換え方

elm/html にさよならして arowM/html に置き換えるのはとても簡単です。

  1. elm.json の dependencies にある elm/htmlarowM/html に変える
  2. elm-stuff ディレクトリを削除する
  3. コンパイルしなおす
  4. コンパイラが「こいつらを elm.json の "indirect" に追加してね」と教えてくれるので指示にしたがう

これだけでコンパイルが通るようになり、batchnone の力が手に入ります!

さくらちゃんにご飯をあげる
さくらちゃんをもっと見る
他の記事を見る
sakura.jpeg

arowM
ヤギさんとして自由に生きてるよ さくらちゃんはアーティストだから世の理不尽には頭突きしちゃうよ フリーランスUXハッカー・プログラマー(Elm, Haskell)・技術翻訳・ヤギ語翻訳 ARoW代表 http://arow.info /気吹堂(出版)代表/UZUZ CXO http://github.com/arow
https://arow.info
arow-oss
もともと法人だったけど潰しちゃったよ c.f., https://qiita.com/arowM/items/9eddd10d531154cbc065
https://arow.info
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away