Nandin Borjigin
Nandin Borjigin

Reputation: 2154

How to store states for sub-modules when using "The Elm Architecture"

I'm new to Function Programming(FP) and Elm, so thinking in FP way is quite challenging for me.

I'm working on a web-app which is very similar to the example of Elm Tutorial.

For the sake of simplicity, we assume the sub-module is a counter. It will display an initial value of 0 and two buttons to increase/decrease that value.

,---.     ,---.
| + | 123 | - |
`---'     `---'

And simplified version of my app is shown below:

-------------------------------------
type alias Model =
    { contents : List Contents.Content
    , routing : Routing
    }

type Routing = List | Edit Int

view : Model -> Html
view model =
    case model.routing of 
        Edit id -> 
            let 
                maybe = List.head << (List.filter (\c -> c.id == id)) model.contents
            in 
                case maybe of 
                    Just content -> Contents.EditView content
                    Nothing -> div [] [ text "Error" ]

        List -> Contents.listView model.contents
------------------------------------
module Contents where 

type alias Content = { someKey : SomeType }

editView : Content -> Html
editView content =
    div []
        [ Counter.view WHERE_SHOULD_I_GOT_A_Counter.Model_FOR_THIS_CALL
        , someOtherViews content
        ]


listView : List Content -> Html
listView = 
    listViewImp
---------------------------
module Counter where

type alias Model = Int

view : Model -> Html
view model =
    div []
        [ button [] [ text "+" ]
        , text (toString model)
        , button [] [ text "-" ]
        ]

There is three-level view hierarchy :

main view ----> edit view --> counter
            |-> list view

The counter value should be 0 every time I navigate to edit view from other views, and then it should be modified only by clicking those two buttons until I leave that page.

The question is where should I get a Counter.Model to pass to Counter.view?

  1. Because the counter is totally independent, so I don't want top level view to know its existence, so it can't be sent from view function.
  2. If I initialize a Counter.Model in editView function, every call to editView (invoked by other actions maybe) will re-initialize the counter to 0

I hope that I have made myself understood.

Thanks for reading all of these.

Upvotes: 0

Views: 445

Answers (1)

Nandin Borjigin
Nandin Borjigin

Reputation: 2154

Thanks to all of you commenting.

After going through the Elm Architecture tutorial again, I noticed that its code structure is somehow different from the one used in Elm Tutorial Gitbook. And for my app, it's better to use the one described in Elm Architecture tutorial.

There is the difference:

  • Elm Architecture defines Model Action update view and init for all the sub module
    • Utility modules are not counted as sub module here
    • some of the Model Action... may be omitted when it is quite simple
  • Elm Tutorial puts the Models and Actions of a certain concept into separate .elm files and has a few View files (Edit.elm List.elm etc.) which are importing the Models and Actions

When a certain concept's different views depend on its Model ONLY(or its variant, List Model for example), we can adopt the structure used in the Elm Tutorial. The reason is any high level modules using that concept would initialize the Model as a part of HighLevelModel. But when there is a view that not only depends on its own 'Model' but also needs another sub module, we can not use the structure of Elm Tutorial. In this case, that view can be treated as a new module (in fact, it is a new module), so it should have its own Model type and be imported by the high level module.

Upvotes: 1

Related Questions