Skip to content

Instantly share code, notes, and snippets.

@kittykatattack
Created October 9, 2017 19:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kittykatattack/38f773e1c1ce336abfea8a12fcd8768a to your computer and use it in GitHub Desktop.
Save kittykatattack/38f773e1c1ce336abfea8a12fcd8768a to your computer and use it in GitHub Desktop.
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