Skip to content

Instantly share code, notes, and snippets.

@trotha01
Last active April 25, 2017 00:55
Show Gist options
  • Save trotha01/c94cf81f7d553e9e7972de06d487ccfd to your computer and use it in GitHub Desktop.
Save trotha01/c94cf81f7d553e9e7972de06d487ccfd to your computer and use it in GitHub Desktop.
Elm example of counter list, showing different ways of splitting it into a module
elm-stuff
index.html
module CounterComponent exposing (Counter, Msg, view, init, update)
import Html exposing (Html, div, button, text)
import Html.Events exposing (onClick)
-- MODEL
type alias Counter =
Int
init : Counter
init =
0
-- UPDATE
type Msg
= Increment
| Decrement
update : Msg -> Counter -> Counter
update msg counter =
case msg of
Increment ->
counter + 1
Decrement ->
counter - 1
-- VIEW
view : Counter -> Html Msg
view counter =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (toString counter) ]
, button [ onClick Increment ] [ text "+" ]
]
module CounterModule exposing (Counter, view, init, increment, decrement)
import Html exposing (Html, div, button, text)
import Html.Events exposing (onClick)
-- MODEL
type alias Counter =
Int
init : Counter
init =
0
-- UPDATE
increment : Counter -> Counter
increment counter =
counter + 1
decrement : Counter -> Counter
decrement counter =
counter - 1
-- VIEW
view : msg -> msg -> Counter -> Html msg
view incrMsg decrMsg counter =
div []
[ button [ onClick decrMsg ] [ text "-" ]
, div [] [ text (toString counter) ]
, button [ onClick incrMsg ] [ text "+" ]
]
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-community/list-extra": "6.0.0 <= v < 7.0.0",
"elm-lang/core": "5.1.1 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}
{-
Not using a counter module, instead keeping everything in one file
-}
module Main exposing (..)
import Html exposing (Html, beginnerProgram, div, button, text)
import Html.Events exposing (onClick)
import List.Extra exposing (updateAt)
main =
beginnerProgram { model = init, view = view, update = update }
-- MODEL
type alias Model =
{ counters : List Counter }
type alias Counter =
Int
type alias Id =
Int
init : Model
init =
{ counters = [ initCounter, initCounter ] }
initCounter : Counter
initCounter =
0
-- UPDATE
type Msg
= Increment Id
| Decrement Id
update : Msg -> Model -> Model
update msg model =
case msg of
Increment id ->
{ model | counters = incrementAt id model.counters }
Decrement id ->
{ model | counters = decrementAt id model.counters }
incrementAt : Int -> List Counter -> List Counter
incrementAt id counters =
case
updateAt id (\counter -> counter + 1) counters
of
Just counters ->
counters
Nothing ->
counters
decrementAt : Int -> List Counter -> List Counter
decrementAt id counters =
case
updateAt id (\counter -> counter - 1) counters
of
Just counters ->
counters
Nothing ->
counters
-- VIEW
view : Model -> Html Msg
view model =
div []
(List.indexedMap
viewCounter
model.counters
)
viewCounter : Int -> Counter -> Html Msg
viewCounter id counter =
div []
[ button [ onClick (Decrement id) ] [ text "-" ]
, div [] [ text (toString counter) ]
, button [ onClick (Increment id) ] [ text "+" ]
]
{-
Using a counter module, but it contains it's own model/view/update
with it's own messages
-}
module Main exposing (..)
import Html exposing (Html, beginnerProgram, div, button, text)
import Html.Events exposing (onClick)
import List.Extra exposing (updateAt)
import CounterComponent as Counter exposing (Counter)
main =
beginnerProgram { model = init, view = view, update = update }
-- MODEL
type alias Model =
{ counters : List Counter }
init : Model
init =
{ counters = [ Counter.init, Counter.init ] }
-- UPDATE
type Msg
= CounterMsg Id Counter.Msg
type alias Id =
Int
update : Msg -> Model -> Model
update msg model =
case msg of
CounterMsg id msg ->
{ model | counters = updateCounterAt id msg model.counters }
updateCounterAt : Int -> Counter.Msg -> List Counter -> List Counter
updateCounterAt id msg counters =
case
updateAt id (Counter.update msg) counters
of
Just counters ->
counters
Nothing ->
counters
-- VIEW
view : Model -> Html Msg
view model =
div []
(List.indexedMap
(\id counter -> Counter.view counter |> Html.map (CounterMsg id))
model.counters
)
{-
Using a counter module, but it contains helper functions
the main logic is still top-level
-}
module Main exposing (..)
import Html exposing (Html, beginnerProgram, div, button, text)
import Html.Events exposing (onClick)
import List.Extra exposing (updateAt)
import CounterModule as Counter exposing (Counter)
main =
beginnerProgram { model = init, view = view, update = update }
-- MODEL
type alias Model =
{ counters : List Counter }
type alias Id =
Int
init : Model
init =
{ counters = [ Counter.init, Counter.init ] }
-- UPDATE
type Msg
= Increment Id
| Decrement Id
update : Msg -> Model -> Model
update msg model =
case msg of
Increment id ->
{ model | counters = incrementAt id model.counters }
Decrement id ->
{ model | counters = decrementAt id model.counters }
incrementAt : Int -> List Counter -> List Counter
incrementAt id counters =
case
updateAt id Counter.increment counters
of
Just counters ->
counters
Nothing ->
counters
decrementAt : Int -> List Counter -> List Counter
decrementAt id counters =
case
updateAt id Counter.decrement counters
of
Just counters ->
counters
Nothing ->
counters
-- VIEW
view : Model -> Html Msg
view model =
let
viewCounter id counter =
Counter.view (Increment id) (Decrement id) counter
in
div []
(List.indexedMap viewCounter model.counters)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment