Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
module ButtonUtilities exposing (..)
import Html exposing (Html, div, text, button, p)
import Html.Events exposing (onClick)
-- Create an ID type that will but used to tag each
-- button in the model's `buttons` array with a unique id
type alias Id =
Int
type ButtonMsg
= ActionOne
| ActionTwo
| ActionThree
-- A model that describes a button
type alias Button =
{ label : String
, id : Id
, msg : ButtonMsg
}
createButton : Id -> String -> ButtonMsg -> Button
createButton id label msg =
{ label = label
, id = id
, msg = msg
}
-- The `buttonsView` helper function is essentially a projection of each button's
-- model state into a visible, HTML element. When a button is clicked,
-- the `update` function is trigged with an `UpdateButton` message. UpdateButton sends
-- the current button element from the model's `buttons` array as its argument
buttonView msg buttonModel =
button [ onClick (msg buttonModel) ] [ text buttonModel.label ]
module Main exposing (..)
import Html exposing (Html, div, text, p)
import ButtonUtilities
-- PART ONE: MODEL
-- The first part of the program defines the main application model
-- and a list that defines and stores the button states
type alias Model =
{ buttons : List ButtonUtilities.Button
, content : String
}
model : Model
model =
{ buttons = buttons
, content = "Nothing yet..."
}
-- A `buttons` list that stores each button's state.
-- (This list is being stored on the main program's `model` - see above)
-- This includes the button's label, unique id, and the action
-- each button should perform
-- Each button will be associated with a unique action that should
-- be performed when it's clicked. A `ButtonMsg` type can help us
-- keep track of these actions
buttons : List ButtonUtilities.Button
buttons =
[ ButtonUtilities.createButton 0 "One" ButtonUtilities.ActionOne
, ButtonUtilities.createButton 1 "Two" ButtonUtilities.ActionTwo
, ButtonUtilities.createButton 2 "Three" ButtonUtilities.ActionThree
]
-- PART 2: UPDATE
-- The second part of the program updates the state of the button that was clcked
-- and performs each button's unique action.
-- (Before you read this code, look ahead to the `view` fundcion in part 3 to see how
-- the `UpadateButton` message is triggerd by the `onClick` event from the
-- `buttonView` function inside the ButtonUtilities module)
-- The `UpdateButton` message takes a button as its argument
-- It will be used to update the state of the currently clicked
-- button and the program's main model
type Msg
= UpdateButton ButtonUtilities.Button
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
-- The currently clicked button is the `clickedButton` that is
-- being passed to the `UpdateButton` message. This can get
-- confusing, so Follow the steps: 1..2..3...4 in
-- order ahead to trace the program flow...
UpdateButton clickedButton ->
let
-- 3. If the button that we're currently looping through
-- matches the `clickedButton` that was passed by the
-- `UpdateButton` message, then update its `label` and pass
-- it back to the model's `buttons` array. Otherwise, just pass
-- the button back unchanged
updateButtonState currentButton =
if clickedButton.id == currentButton.id then
{ currentButton | label = clickedButton.label ++ "!" }
else
currentButton
-- 2. Loop through all the elements in the model's `buttons`
-- array to find the currently clicked button and update its state
updateButtons model =
{ model | buttons = List.map updateButtonState model.buttons }
in
-- 1. Start here! First, let's take the current model and update the buttons
( model
|> updateButtons
-- 4. Now that the button's state has been updated, and the
-- model's `buttons` array has been updated,
-- let's perform the clicked button's unique action using the
-- `performButtonAction` helper function (which you'll see
-- in the code ahead)
|>
performButtonAction clickedButton
, Cmd.none
)
-- `performButtonAction` is a helper function that updates the main
-- program's model's`content` based on the value of the clicked button's `msg`
performButtonAction : ButtonUtilities.Button -> Model -> Model
performButtonAction button model =
case button.msg of
ButtonUtilities.ActionOne ->
{ model | content = "Hello from Button One!" }
ButtonUtilities.ActionTwo ->
{ model | content = "Button Two says Hi!" }
ButtonUtilities.ActionThree ->
{ model | content = "Unbelievable! It's button Three!" }
-- PART 3: VIEW
-- Display the buttons, the model's current text content, and
-- handle each button's `onClick` event
view : Model -> Html Msg
view model =
div []
[ div []
-- Loop through each of the elements in the model's `buttons`
-- array and display them using the `buttonsView` helper function ahead
(List.map (ButtonUtilities.buttonView UpdateButton) model.buttons)
-- Display the model's current `content` string
, p [] [ text model.content ]
]
-- PART 4: MAIN APP WIRING
-- The standard Elm Architecture boilerplate
main : Program Never Model Msg
main =
Html.program
{ view = view
, update = update
, subscriptions = \_ -> Sub.none
, init = ( model, Cmd.none )
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.