# Elm spa example header with shared button (on Click) attribute

**URL:** <https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710>\
**Category:** Learn\
**Created:** [November 21, 2019, 12:03pm UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710 "2019-11-21T12:03:26Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nikolis\_Galerakis](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/nikolis_galerakis/32/2479_2.png) [@Nikolis\_Galerakis](https://discourse.elm-lang.org/u/Nikolis_Galerakis)\
**Post date:** [November 21, 2019, 12:03pm UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/1 "2019-11-21T12:03:27Z")

</div>

Hello Folks,

So I am developing an application using the elm-spa-example by rfeldman.  
I lately found my self in a situation where I would like to include server generated content on the header which responds to onCLick events .

Kind of how Facebook notifies you whether new messages for you came in.  
The problem I think is apparent in the elm-spa-example the main method is the aggregator and every Page has it’s own message type and main has a Custom Msg type with variants for every possible page msg type in the application.

Then in the module that creates the view (Page.view) it passes the view of the particular page that is supposed to be on the screen which is of type Html PageMsgType and the Main method is mapping it to it’s local message type which has a variant for every posible PageMsgType containing the PageMsgType so it can then parse the message when a component is clicked or something and forward it to the appropriate update function of the particular page.

My problem now is that I would like to implement the functionality described above and what I actually was thinking of is create a button with events that are handled in the Main module but somehow it’s not possible (at least as far as I can understand) because what I am actually trying to do is compose a an Documet with more than one Msg types, PageMsgType and MainMsgType .

Have you ever encountered a situation like the described before ? How would you go with this ?

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [November 21, 2019, 7:37pm UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/2 "2019-11-21T19:37:59Z")

</div>

One way could be to render the header in the `Main` outside the page specific view (without using `Html.map`).

I think it is quite common for SPAs to render the layout of the app (header or app bar, footer, menu) this way in `Main` with `Main` messages, and then render the page only inside its container with `Html.map`.

Something like:

```elm
type Msg
    = HeaderClicked
    | ChangedUrl Url
    | ClickedLink Browser.UrlRequest
    | GotHomeMsg Home.Msg
    ...

view : Model -> Document Msg
view model =
    let
        viewer =
            Session.viewer (toSession model)

        viewPage page toMsg config =
            let
                { title, body } =
                    Page.view viewer page config
            in
            { title = title
            , body = viewHeader :: List.map (Html.map toMsg) body
            }
    in
    ...

viewHeader : Html Msg
viewHeader =
    div []
        [ button
            [onClick HeaderClicked]
            [text "Click me"]
        ]

```

and you would remove the banner view from each page.

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [November 22, 2019, 4:23am UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/3 "2019-11-22T04:23:45Z")

</div>

> [@Nikolis\_Galerakis](#):
>
> Have you ever encountered a situation like the described before ? How would you go with this ?

The way I model this is to have global state and global messages. This global state is updated in the `Main` and sent down to the `view` and the `update` of pages as a form of context.

A very similar pattern is [elm-shared-state](https://github.com/ohanhi/elm-shared-state) (formerly elm-taco).

---

<div class="post-metadata">

**Author:** ![Nikolis\_Galerakis](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/nikolis_galerakis/32/2479_2.png) [@Nikolis\_Galerakis](https://discourse.elm-lang.org/u/Nikolis_Galerakis)\
**Post date:** [November 22, 2019, 7:29am UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/4 "2019-11-22T07:29:56Z")

</div>

Looks like the obvious answer, I was just avoiding to put to much on the Main because of fear it becomes to big and more complex than I can manage. And because of a comment by RFeldman saying  
“-- NOTE: Based on discussions around how asset management features  
– like code splitting and lazy loading have been shaping up, it’s possible  
– that most of this file may become unnecessary in a future release of Elm.  
– Avoid putting things in this module unless there is no alternative!”  
but I guess there is not apparent alternative on this one.

---

<div class="post-metadata">

**Author:** ![Nikolis\_Galerakis](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/nikolis_galerakis/32/2479_2.png) [@Nikolis\_Galerakis](https://discourse.elm-lang.org/u/Nikolis_Galerakis)\
**Post date:** [November 22, 2019, 7:32am UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/5 "2019-11-22T07:32:00Z")

</div>

Thank you I will consider this approach carefully.

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [November 22, 2019, 8:01am UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/6 "2019-11-22T08:01:49Z")

</div>

> [@Nikolis\_Galerakis](#):
>
> I was just avoiding to put to much on the Main because of fear it becomes to big and more complex than I can manage.

This is a good attitude. You usually have only one `Main.elm` and it pays to take extra care not to make it a magnet for things that would have ended up in other modules with more careful consideration.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [November 22, 2019, 8:13am UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/7 "2019-11-22T08:13:24Z")

</div>

The `viewHeader` function in my example does not have to be literally in the `Main.elm` module.  
It can be in its own module, taking a `msg` argument:

```auto
module Main exposing (main)

import Header

type Msg
    = HeaderClicked
    | GotHomeMsg Home.Msg

view model =
            ...
            in
            { title = title
            , body = Header.view HeaderClicked :: List.map (Html.map toMsg) body
            }

```

```auto
module Header exposing (view)

view : msg -> Html msg
view onClick = 
    div []
    [ button
        [onClick msg]
        []
    ]

```

or if really needed could have its own `Msg` which would be mapped like the pages ones.

At the end, all messages are `Main` ones, for example:

```auto
type Msg
    = HeaderMsg Header.Msg
    | GotHomeMsg Home.Msg
    ...

view model =
            ...
            in
            { title = title
            , body = Html.map HeaderMsg viewHeader :: List.map (Html.map toMsg) body
            }

```

I would strongly prefer the first solution (the `msg` argument(s)) as long as one or two messages for the header are enough.

Lastly:

> [@Nikolis\_Galerakis](#):
>
> I was just avoiding to put to much on the Main because of fear it becomes to big and more complex than I can manage.

Try to structure by types, not by code size.  
See [The life of a file](https://www.youtube.com/watch?v=XpDsk374LDE).

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [November 22, 2019, 2:31pm UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/8 "2019-11-22T14:31:58Z")

</div>

> [@Nikolis\_Galerakis](#):
>
> “-- NOTE: Based on discussions around how asset management features  
> – like code splitting and lazy loading have been shaping up, it’s possible  
> – that most of this file may become unnecessary in a future release of Elm.  
> – Avoid putting things in this module unless there is no alternative!”

I think that comment was written prior to 0.19, when there were ideas about code splitting floating around. That never made it into 0.19, and I think those ideas may now be abandoned. Partly due to dead code elimination in 0.19 reducing asset sizes and making code splitting less of an advantage as a result.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [December 2, 2019, 2:31pm UTC](https://discourse.elm-lang.org/t/elm-spa-example-header-with-shared-button-on-click-attribute/4710/9 "2019-12-02T14:31:59Z")

</div>

Closed on December 2, 2019, 2:31pm UTC

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
