LoginSignup
5
2

More than 5 years have passed since last update.

Elm備忘録 ~Html.Keyedの活用[前編]

Last updated at Posted at 2019-02-25

Elm備忘録 ~Html.Keyedの活用[前編]~

  • type=fileのinput要素で活用する
  • type=file, inputの仕様
    • 同じファイルを二度連続で選択したときonChangeが発火しない(changeしてないからその通りっちゃあそのとおり)
  • これでは困ることがある
  • 別のフォームでの入力値が変わったときにinput要素でたとえ同じファイルでももう一度onChangeしてほしい!
    • 別のフォームでの入力でバリデーションの条件変わったりとかあるでしょ?あったのよ
  • Html.Keyedを使って別のフォームの入力値が変わったときにinput要素を再生成させることで切り抜ける

  • Html.Keyed.nodeはHtml要素を生成させるための関数(ざっくりいうとね)だが、Html.nodeと違うのは第三引数

    • Html.nodeは List (Html msg)
    • Html.Keyedは List (String, Html msg)
    • になっている。2つとも要素のchildrenを指定できる引数となっている
    • Keyedのほうはchildrenとその各要素対してStringでkeyを指定する
    • keyが指定されるとどうなるのか?VirtualDomのDiffを計算するフェーズでKeyが一致しなければ要素が再生成されることになる
    • なのでfile=typeのinput以外のフォームによる入力値をkeyにすることで、それが変わるとfile=typeのinputは再生されて、同じファイルを選択したときにも再びonChangeが発火する
  • before

type Msg
    = ChangedCategory String
    | SelectedFile String


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ChangedCategory category ->
            ( { model | selectedCategory = category }, Cmd.none )

        SelectedFile filePath ->
            ( { model | selectedFilePathMessage = Just (filePath ++ "|category:" ++ model.selectedCategory) }, Cmd.none )



---- VIEW ----


filePathMessage : Maybe String -> Html msg
filePathMessage strM =
    strM |> Maybe.withDefault "ファイルが選択されてません" |> Html.text


view : Model -> Html Msg
view model =
    div []
        [ Html.div
            []
            [ Html.input [ onInput SelectedFile, Html.Attributes.type_ "file" ] []
            , model.selectedCategory
            , filePathMessage model.selectedFilePathMessage
            ]
        , Html.div []
            [ Html.text "ファイル種類: "
            , Html.select [ onInput ChangedCategory ]
                [ Html.option [ Html.Attributes.value "csv" ]
                    [ Html.text "csv"
                    ]
                , Html.option [ Html.Attributes.value "tsv" ]
                    [ Html.text "tsv"
                    ]
                , Html.option [ Html.Attributes.value "plain" ]
                    [ Html.text "plain"
                    ]
                ]
            ]
        ]
  • after
type Msg
    = ChangedCategory String
    | SelectedFile String


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ChangedCategory category ->
            ( { model | selectedCategory = category }, Cmd.none )

        SelectedFile filePath ->
            ( { model | selectedFilePathMessage = Just (filePath ++ "|category:" ++ model.selectedCategory) }, Cmd.none )

---- VIEW ----

filePathMessage : Maybe String -> Html msg
filePathMessage strM =
    strM |> Maybe.withDefault "ファイルが選択されてません" |> Html.text

view : Model -> Html Msg
view model =
    div []
        [ Keyed.node "div" -- 変わったよ!
            []
            [ ( model.selectedCategory, Html.input [ onInput SelectedFile, Html.Attributes.type_ "file" ] [] )
            , ( model.selectedCategory, filePathMessage model.selectedFilePathMessage )
            ]
        , Html.div []
            [ Html.text "ファイル種類: "
            , Html.select [ onInput ChangedCategory ]
                [ Html.option [ Html.Attributes.value "csv" ]
                    [ Html.text "csv"
                    ]
                , Html.option [ Html.Attributes.value "tsv" ]
                    [ Html.text "tsv"
                    ]
                , Html.option [ Html.Attributes.value "plain" ]
                    [ Html.text "plain"
                    ]
                ]
            ]
        ]
5
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2