Suppose I want to create a webpage with two components, say a Navbar and a Body. These two components do not interact with each other and can be developed independently. So, I have two elm files which have the following components in each of them:
type Model = ...
type Msg = ...
init : (Model, Cmd Msg)
update : Msg -> Model -> (Model, Cmd Msg)
view : Model -> Html Msg
Assumming that they both work fine, how do we compose them to make a program which has both these components?
I tried writing something like this:
type Model = {body : Body.Model , navbar : Navbar.Model}
type Msg = BodyMsg Body.Msg | NavbarMsg Navbar.Msg
view : Model -> Html Msg
view model = div [] [Body.view model.body, Navbar.view model.navbar]
update : Msg -> Model -> (Model, Cmd Msg)
update = ...
The above gets ugly quickly when I try to write this update function. In particular, once I extract the Msg's out of the Cmd's update functions from Navbar.update or Body.update, how do I extract them and feed them back to these functions again? Also, the view function above does not particularly look idiomatic.
What is the elm-architecture recommended way to solve this problem? Is this pattern idiomatic in elm-architecture?
Yes, you're on the right path.
In the view you need to use
Html.map.Body.view model.bodyhas typeHtml Body.Msgwhich requires us to useHtml.mapto get the correct type ofHtml Msg. Similarly forNavbar.view model.navbar.And, for the
updatefunction you'd write it like so:In the
BodyMsgcase,newBodyhas typeBody.Modeland so we can set thebodyfield inmodelto it. However,newCmdhas typeCmd Body.Msgand so before we can return we need to useCmd.mapto get the correct return type ofCmd Msg.Similar reasoning can be used for the
NavbarMsgcase.What bothers you about the view code?
N.B. This answer assumes you're using Elm 0.18.