Skip to content

Instantly share code, notes, and snippets.

@eXenon
Created May 8, 2018 20:16
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 eXenon/ef7652710816d2a2f0a9167d0a72510f to your computer and use it in GitHub Desktop.
Save eXenon/ef7652710816d2a2f0a9167d0a72510f to your computer and use it in GitHub Desktop.
A simple example file in Elm for a list with editable elements
module Main exposing (..)
import Html exposing (Html, button, div, text, ul, li, input)
import Html.Events exposing (onClick, onInput)
import Html.Attributes exposing (placeholder, value)
import List exposing (map, length)
main =
Html.beginnerProgram { model = model, view = view, update = update }
-- HELPERS
removeByIndex : Int -> List a -> List a
removeByIndex idx l =
case l of
[] ->
[]
hd :: tl ->
if idx == 0 then
tl
else
hd :: (removeByIndex (idx - 1) tl)
replaceAtIndex : Int -> a -> List a -> List a
replaceAtIndex idx newvalue l =
case l of
[] ->
[]
hd :: tl ->
if idx == 0 then
newvalue :: tl
else
hd :: (replaceAtIndex (idx - 1) newvalue tl)
-- MODEL
type alias Item =
{ value : String
, index : Int
, isBeingEdited : Bool
, newValue : String
}
type alias Model =
{ items : List Item
, newValue : String
}
model : Model
model =
{ items = [], newValue = "" }
-- UPDATE
type Msg
= AddElement String
| StartEditingElement Int
| EditElement Int String
| RemoveElementByIndex Int
| PreparingNewElement String
| PreparingEditElement Int String
update : Msg -> Model -> Model
update msg model =
case msg of
AddElement s ->
case s of
"" ->
model
_ ->
{ model
| items = { value = s, index = (length model.items), isBeingEdited = False, newValue = "" } :: model.items
, newValue = ""
}
StartEditingElement i ->
let
updater =
\i e ->
if e.index == i then
{ e
| isBeingEdited = True
, newValue = e.value
}
else
e
in
{ model | items = (map (updater i) model.items) }
EditElement i s ->
let
updater =
\i s e ->
if e.index == i then
{ e
| value = s
, isBeingEdited = False
}
else
e
in
{ model | items = (map (updater i s) model.items) }
RemoveElementByIndex i ->
{ model | items = removeByIndex i model.items }
PreparingNewElement s ->
{ model | newValue = s }
PreparingEditElement i s ->
let
updater =
\i s e ->
if e.index == i then
{ e | newValue = s }
else
e
in
{ model | items = (map (updater i s) model.items) }
-- VIEW
viewListElement : Item -> Html Msg
viewListElement item =
if item.isBeingEdited then
li []
[ input
[ value item.newValue
, onInput (PreparingEditElement item.index)
]
[]
, button [ onClick (EditElement item.index item.newValue) ]
[ text "Save" ]
]
else
li []
[ text (item.value ++ " ")
, button [ onClick (StartEditingElement item.index) ]
[ text "✎" ]
, button [ onClick (RemoveElementByIndex item.index) ]
[ text "×" ]
]
view : Model -> Html Msg
view model =
div []
[ input
[ placeholder "Add item to list"
, onInput PreparingNewElement
, value model.newValue
]
[]
, button [ onClick (AddElement model.newValue) ]
[ text "+" ]
, ul [] (map viewListElement model.items)
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment