How to structure inter-component communication

254 views
Skip to first unread message

Richard Osafo

unread,
Apr 18, 2016, 10:42:42 AM4/18/16
to Elm Discuss
Hi,
Doing some tests with elm and I have the following structure

MainContainer (component)
  • Top Panel (component)
    • Log out (button)
    • User (div)
  • Side Bar (component)
    • List with links
  • Content Pane (component)
    • List of cards / tabs

Clicking on "User" or the links in the "Side Bar" or some other link in the card/tabs should cause a new tab/card to be added to the content pane.
What is the best way to go about this?


The currently implementation involves altering the update function to return messages (update : Action -> Model -> (Model, Effects Action, List Message). When the update function completed, the parent can look at the messages and process the ones that apply.

E.g. User --> TopPanel --> MainContainer --> ContentPane


It works some times but some messages are lost because since each update returns messages, it is difficult when to stop.


Any ideas on how an event (e.g. click) in one component trigger update in another component?


regards,
Richard.


Simon

unread,
Apr 20, 2016, 11:52:46 AM4/20/16
to Elm Discuss
I think the idiomatic way is to pattern match against actions that require cross-component communication at the lowest parent of the two components, and then redirect from there
In any event, that's what I do.

Richard Osafo

unread,
Apr 20, 2016, 1:24:44 PM4/20/16
to Elm Discuss
Can you give me a sample? Very much interested in a possible solution.

Simon

unread,
Apr 21, 2016, 12:56:13 AM4/21/16
to Elm Discuss

Take a look at this

        UserAction act ->
            case act of
                User.SidebarAction (Sidebar.SwitchPage LogOff) ->
                    init
                _ ->
                    let
                        (m, e) = User.update act model.user
                    in
                    ( { model | user = m }
                    , Effects.map UserAction e
                    )

Notice how this parent component watches out for one particular child Action and uses that to send an Action to a different child. All other actions are passed down to the destination component as normal

Simon

James Wilson

unread,
Apr 21, 2016, 8:10:09 AM4/21/16
to Elm Discuss
This reminds me semi randomly of pattern synonyms from Haskell make it here. They allow you basically to do something like:

pattern LogOffAction = User.SidebarAction (Sidebar.SwitchPage LogOff)

...

case act of
   
LogOffAction -> init
   _
-> ...

A module could export patterns and parent modules could build off them, so youd end up with synonyms that can match against very nested things easily.

That all said, I guess a similar thing could be done by exporting functions so youd end up with eg.

if Sidebar.isLogOffAction action then init

I quite liked another approach I saw, where you thread actions down as usual, having child components perform updates, but then export an API from the child components  that allows you to discover interesting things about the state (such as the value of the input. For more global things like log off I would think about having a top level Services that come with some state and a Signal.Address (which is wired up to send actions back to the service. the service could then expose an API like "MyService.logOff service" which fired a logoff action to the services address, triggering it to update its knowledge of current user or whatever. If that service is just passed down to the main secitons of your page, they can query it directly to see what the login state is, and anything can send events to it using its API (which internall just uses the Signal.Address it contains).

Bit of a ramble but perhaps it'll be of interest!

Richard Osafo

unread,
Apr 21, 2016, 12:04:56 PM4/21/16
to Elm Discuss
I get what you mean now. Will see how to apply it to more nested components. Thanks.
Reply all
Reply to author
Forward
0 new messages