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 a
mapof
Search.Modelinto a
Modeland a
Cmd SearchMsginto a
Cmd Msgand returns them in a
tuple`.
The above design is mainly to replace the actual Model
and trigger extra Cmd
s based on the Url
, to perform this extra Cmd
s 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