I think this depends on how you want a design the pages, I will try first analyze the code, explain the consequences, gives you an alternative and then you can model under your convenience a solution.
In the Main.elm is use only on the initialization of a page, I will try first to explain what is doing this code (maybe is redundant and you already understand, sorry if is that the case):
Based on the code they only use the Cmd.map on the stepXxx functions that are used in the stepUrl. So I will explain the architecture with the first stepXxx function and the stepUrl:
stepSearch : Model -> ( Search.Model, Cmd Search.Msg ) -> ( Model, Cmd Msg )
stepSearch model (search, cmds) =
( { model | page = Search search }
, Cmd.map SearchMsg cmds
)
This function takes a record with a { key : Nav.Key, page : Page } , and map the ( Search.Model, Cmd Search.Msg ) into a ( Model, Cmd Msg ), So this function is amapofSearch.Modelinto aModeland aCmd SearchMsginto aCmd Msgand returns them in atuple`.
The above design is mainly to replace the actual Model and trigger extra Cmds based on the Url, to perform this extra Cmds he needs to use the Cmd.map.
Disadvantages: Well the main one is that the Search.init function is not aware of that mapping so you can not expect that a Cmd SearchMsg Search.Msg is created if you are on the scope of that function.
How to avoid this?
Well if you want to give to the init function more context you can add an attribute (Msg -> msg) as part of the Seach.init function.
The actual implementation is like:
init : Session.Data -> ( Model, Cmd Msg )
init session =
case Session.getEntries session of
Just entries ->
( Model session "" (Success entries)
, Cmd.none
)
Nothing ->
( Model session "" Loading
, Http.send GotPackages <|
Http.get "/search.json" (Decode.list Entry.decoder)
)
And the new one will be like:
init : (Msg -> msg) -> Session.Data -> ( Model, Cmd msg )
init parentMsg session =
case Session.getEntries session of
Just entries ->
( Model session "" (Success entries)
, Cmd.none
)
Nothing ->
( Model session "" Loading
, Http.send (parentMsg << GotPackages) <|
Http.get "/search.json" (Decode.list Entry.decoder)
)
Also we need to change the original stepSearch to:
stepSearch : Model -> ( Search.Model, Cmd Msg ) -> ( Model, Cmd Msg )
stepSearch model (search, cmds) =
( { model | page = Search search }, cmds )
And pass the SearchMsg to the Session.init on the stepUrl function:
-- Irrelevant code line 212
oneOf
[ route top
( stepSearch model (Search.init SearchMsg session)
)
-- Irrelevant code line 217