使用带有Elm的动态数量的按钮

时间:2017-01-13 18:49:04

标签: elm

我想创建一些按钮,其数量会随用户操作而变化(列表或数组中每个值一个)。

我可以创建按钮但不知道在update中按了哪个按钮。

例如,在下面的简化代码中,如何增加与按下的按钮对应的data中的值?

module Main exposing (..)

import Html exposing (..)
import Html.Events exposing (..)
import Array exposing (..)

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

-- MODEL

type alias Model =
    { data : Array Int
    }

init : ( Model, Cmd Msg )
init =
    ( Model (fromList [ 11, 22, 33 ]), Cmd.none )

-- UPDATE

type Msg
    = Play  -- or Play Int ?


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Play ->
            ( model, Cmd.none )

-- VIEW

view : Model -> Html Msg
view model =
    div [] (Array.map viewButton model.data |> toList)

viewButton : Int -> Html Msg
viewButton v =
    div [] [ button [ onClick Play ] [ text (toString v) ] ]

subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none

1 个答案:

答案 0 :(得分:3)

您对Msg可能拥有Play Int构造函数的评论走在正确的轨道上。我们通常在Elm处理这个问题的方法是携带索引。您可以使用Array.indexedMap函数中的view来提取索引和数据。

以下是代码相关部分的更新版本,只有一些更改会使点击时的每个按钮递增:

type alias Model =
    { data : Array Int
    }

-- UPDATE
type Msg
    = Play Int

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Play idx ->
            ( { model | data = incrementAt idx model.data }, Cmd.none )

incrementAt : Int -> Array Int -> Array Int
incrementAt idx arr =
    let
        cur =
            Maybe.withDefault 0 (get idx arr)
    in
        set idx (cur + 1) arr

-- VIEW
view : Model -> Html Msg
view model =
    div [] (Array.indexedMap viewButton model.data |> toList)

viewButton : Int -> Int -> Html Msg
viewButton idx v =
    div [] [ button [ onClick (Play idx) ] [ text (toString v) ] ]

此代码段可在runelm.io上找到。