Last active
July 25, 2016 18:27
-
-
Save piotrkubisa/d5225c285bd98eb801a2ca9ac4028283 to your computer and use it in GitHub Desktop.
Recursive module in Elm with update
This file contains hidden or 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 Categories exposing (Model, Msg, init, update, view) | |
| import Html exposing (..) | |
| import Html.Attributes exposing (style) | |
| import Html.Events exposing (onInput, onClick) | |
| type alias Model = | |
| { entry : String | |
| , path : Path | |
| , children : Children | |
| } | |
| type Children | |
| = Children (List Model) | |
| type alias Path = | |
| List Int | |
| init : Model | |
| init = | |
| { entry = "hello world" | |
| , path = [] | |
| , children = | |
| Children | |
| [ { entry = "hello2" | |
| , path = [ 0 ] | |
| , children = | |
| Children | |
| [ { entry = "hello 3", path = [ 0, 0 ], children = Children [] } | |
| , { entry = "hello 4", path = [ 0, 1 ], children = Children [] } | |
| , { entry = "hello 5", path = [ 0, 2 ], children = Children [] } | |
| ] | |
| } | |
| , { entry = "hello 6", path = [ 1 ], children = Children [] } | |
| , { entry = "hello 7", path = [ 2 ], children = Children [] } | |
| ] | |
| } | |
| model : Model | |
| model = | |
| init | |
| wrap : List Model -> Children | |
| wrap children = | |
| (Children children) | |
| unwrap : Children -> List Model | |
| unwrap (Children children) = | |
| children | |
| createTask : String -> Path -> Model | |
| createTask entry path = | |
| { entry = entry | |
| , path = path | |
| , children = Children [] | |
| } | |
| {-| | |
| Not used | |
| -} | |
| prependTask : String -> Path -> Children -> Children | |
| prependTask entry path (Children children) = | |
| let | |
| task = | |
| createTask entry path | |
| in | |
| Children (task :: children) | |
| appendTask : String -> Path -> Children -> Children | |
| appendTask entry path (Children children) = | |
| let | |
| task = | |
| createTask entry path | |
| in | |
| wrap (children ++ [ task ]) | |
| -- UPDATE | |
| type Msg | |
| = NoOp | |
| | Write String | |
| | WriteTo Model String | |
| | Append Path | |
| | AppendTo Model | |
| update : Msg -> Model -> Model | |
| update msg model = | |
| case msg of | |
| Write newEntry -> | |
| { model | entry = newEntry } | |
| WriteTo item newEntry -> | |
| updateAt update item.path (Write newEntry) model | |
| Append path -> | |
| { model | children = (appendTask model.entry path (model.children)) } | |
| AppendTo item -> | |
| let | |
| path = | |
| case List.tail (item.path) of | |
| Nothing -> | |
| [ (List.length (unwrap item.children)) ] | |
| Just pos -> | |
| item.path ++ [ (List.length (unwrap item.children)) ] | |
| in | |
| updateAt update item.path (Append path) model | |
| NoOp -> | |
| model | |
| {-| | |
| That snippet was made by @szabba from Elm's Slack | |
| -} | |
| updateAt : (a -> Model -> Model) -> Path -> a -> Model -> Model | |
| updateAt update path msg model = | |
| case path of | |
| [] -> | |
| update msg model | |
| branch :: rest -> | |
| let | |
| newChildren = | |
| model.children | |
| |> childrenIxMap | |
| (\ix child -> | |
| if ix == branch then | |
| updateAt update rest msg child | |
| else | |
| child | |
| ) | |
| in | |
| { model | children = newChildren } | |
| childrenIxMap : (Int -> Model -> Model) -> Children -> Children | |
| childrenIxMap f (Children children) = | |
| children | |
| |> List.indexedMap f | |
| |> Children | |
| -- VIEW | |
| view : Model -> Html Msg | |
| view model = | |
| div [] | |
| [ ul [] [ (viewItem model) ] | |
| ] | |
| viewList : Children -> List (Html Msg) | |
| viewList (Children children) = | |
| List.map viewItem children | |
| viewItem : Model -> Html Msg | |
| viewItem item = | |
| li [] | |
| [ div [] [ text item.entry ] | |
| , (viewForm item) | |
| , ul [] (viewList item.children) | |
| ] | |
| viewForm : Model -> Html Msg | |
| viewForm item = | |
| let | |
| btnLabel = | |
| "append to " ++ (toString item.entry) ++ " path: " ++ (toString item.path) | |
| in | |
| div [ style [] ] | |
| [ input [ style [], onInput (WriteTo item) ] [] | |
| , button [ style [], onClick (AppendTo item) ] [ text btnLabel ] | |
| ] |
Author
Thank you! I have updated to make it working with Append/Write events
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You could try something like