2017-01-13 6 views
0

Я хотел бы создать несколько кнопок, число которых будет варьироваться в зависимости от действий пользователя (по одному на значение в списке или массиве)).Используйте динамическое число кнопок с 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 

ответ

2

Вы на правильном пути с вашим комментарием о 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.

Смежные вопросы