Starting from those three declarations :
type SharedMsg
= SharedAction
type Page1Msg
= Page1Action
type Page2Msg
= Page2Action
I there a way to obtain an equivalent of the following one? Like a way to "merge" union types ?
type Msg
= SharedAction
| Page1Action
| Page2Action
=============================
Context : I am splitting an Elm application into one module per page with their own folders.
Some actions will be shared, and some actions will be page-specific.
If I was to use the Html.map
method, I feel that I would have to re-write every shared action that a page uses in its own PageMsg
message type:
type Page1Msg
= Page1Action
| SharedAction
type Msg
= Page1Msg Page1Msg
| Page2Msg Page2Msg
view : Model -> Html Msg
view =
Html.map Page1Msg (Page1View.view model)
Hence my thinking of using a unique Msg
type for all pages, but preserving modularity by writing page-specific messages in their own folders, and then somehow defining a unique Msg
type by merging them.
@z5h's answer is almost correct, but the type constructors have to have different names.
You can't merge the types the way you'd like to.
As for the idiomatic way: You would name the split types just Msg
, not Page1Msg
. So, for example:
Page1.elm:
module Page1 exposing (Msg)
type Msg
= Foo
Page2.elm:
module Page2 exposing (Msg)
type Msg
= Bar
Shared.elm:
module Shared exposing (Msg)
type Msg
= Baz
Main.elm:
module Main exposing (..)
import Shared
import Page1
import Page2
type Msg
= SomethingCustom
| SharedMsg Shared.Msg
| Page1Msg Page1.Msg
| Page2Msg Page2.Msg
By the way, remember that if you split the modules into Page1.View
, Page1.Types
, etc., then as long as the exposed functions don't overlap, you can import different modules under the same name, ie:
import Page1.Types as Page1
import Page1.State as Page1
import Page1.View as Page1
import Page1.Decoders as Page1
Do not forget that you are absolutely not obliged to follow the update-view definitions exactly as in the basic examples. In your case, you could adapt the update function to your needs
how about in parent:
update message model =
let
sharedMsgs =
{ msg1 = Msg1
, msg2 = Msg2
}
in case message of
Page1Msg msg ->
let (m, c) =
update sharedMsgs msg model.page1
in case c of
Nothing ->
m
Just c ->
update c m
where the update function in page1 has signature
update : SharedMessages msg -> Msg -> Page1Model -> (Page1Model, Maybe msg)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With