Created
May 8, 2018 20:16
-
-
Save eXenon/ef7652710816d2a2f0a9167d0a72510f to your computer and use it in GitHub Desktop.
A simple example file in Elm for a list with editable elements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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