Use a dynamic number of buttons with Elm

ぐ巨炮叔叔 提交于 2020-01-07 03:04:30

问题


I would like to create some buttons whose number will vary with user actions (one per value in a list or array)).

I'm able to create the buttons but not to know in update which one was pressed.

For instance, in the following reduced code, how can I increment the value in data corresponding to the pressed button?

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:


You are on the right track with your comment about Msg maybe having a Play Int constructor. The way we usually handle this in Elm is by carrying around the index. You can use Array.indexedMap in the view function to pull both the index and data.

Here is an updated version of the relevant parts of your code with only a few changes that increments each button on click:

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) ] ]

This snippet is available on runelm.io.



来源:https://stackoverflow.com/questions/41641476/use-a-dynamic-number-of-buttons-with-elm

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!