As a quick note to anyone struggling with how to perform app wide 
inter-component communication in elm 0.17 (e.g. anyone building a 
non-trivial SPA), here is one simple way to setup pubsub style 
communication using Elm Ports and Subscriptions. 

In this example, ChildOne will broadcast a message that ChildTwo is 
listening for.

Ports.elm
*port* module Ports exposing (..)

-- dispatchSomeMessage will create a command with a
-- string payload representing an important message
-- to broadcast to listening components.

port *dispatchSomeMessage* : String -> Cmd msg


-- receiveSomeMessage is the port which our components 
-- subscribe to receive the dispatched message

port *receiveSomeMessage* : (String -> msg) -> Sub msg


The Ports.elm file contains all of the port specifications in the app. In 
this case it defines a two ports: one port for dispatching a message, and 
another for receiving a message. The module declaration at the top of the 
file must be preceded by "port".

index.js
var app = Elm.Main.fullscreen();

app.ports.*dispatchSomeMessage*.subscribe(function(msg) {
    app.ports.*receiveSomeMessage*.send(msg);
});

This is where the behaviour of all ports are defined in javascript. In this 
case the dispatchSomeMessage function is receiving a msg argument from Elm, 
and then quickly sending that message back into Elm through the 
receiveSomeMessage port.

ChildOne.elm
module ChildOne exposing (..)

import Ports exposing (..)
import Html exposing (Html, button, text)
import Html.Events exposing (onClick)


type alias Model = String


type Msg
    = Click

subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Click ->
            ( model, *dispatchSomeMessage "Hello World!"* )


view : Model -> Html Msg
view model =
    button [ onClick Click ] [text "Click Me"]


ChildOne dispatches the message "Hello World!" through the 
dispatchSomeMessage port when a button in the view is clicked. The message 
is then routed from the dispatchSomeMessage port, directly back into the 
receiveSomeMessage port as defined in index.js

ChildTwo.elm
module ChildTwo exposing (..)

import Ports exposing (..)
import Html exposing (Html, text)

type alias Model = 
        { message : String }

type Msg
    = ChangeMessage String

subscriptions : Model -> Sub Msg
subscriptions model =
    *receiveSomeMessage **ChangeMessage*


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ChangeMessage msg ->
            ({ model | message = msg }, Cmd.none )


view : Model -> Html Msg
view model =
    text model.message

ChildTwo subscribes a ChangeMessage tag to the 'receiveSomeMessage' port. 
When the port receives the "Hello World" message from ChildOne, ChildTwo 
updates its models message, and re-renders the view.

Main.elm
module Main exposing (..)

import ChildOne
import ChildTwo

type alias Model =
    { childOneModel : ChildOne.model
    , childTwoModel : ChildTwo.model
    }

-- ..init func. nothing special here. 

type Msg
    = ChildOneMsg ChildOne.Msg
    | ChildTwoMsg ChildTwo.Msg


subscriptions : Model -> Sub Msg
subscriptions model =
*    Sub.batch*
*        [ Sub.map ChildOneMsg (ChildOne.subscriptions 
model. childOneModel)*
*        , Sub.map ChildTwoMsg (ChildTwo.subscriptions 
model. childTwoModel)*
*        ]*

-- .. update function. nothing special here. 

main : Program Never
main =
    Html.App.program
        { init = init
        , update = update
        , view = view
        , subscriptions = subscriptions
        }



Main.elm batches the subscriptions defined in child components. That's all 
there is to it. Nice and clean inter-component communication.

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to