It's a neat idea, but it makes me uncomfortable, because it introduces a 
possible source of errors into the application. What if a message is 
dispatched to the wrong port?

The code that I posted at the top of this thread is a simplistic example of 
how to dispatch messages across your app, but you probably don't want to be 
communicating with simple primitives (String, Int, etc). Just like you use 
union types for messages within TEA components, use union types for your 
app wide messages as well. 

For example, if you need to broadcast/subscribe to some app wide events, 
you could create an Events.elm module that isolates all of this logic:

port module Events exposing (Event(..), publish, subscribe)


type Event
    = SomethingHappened
    | SomethingElseHappened Int


type alias DTO = 
  (String, String)

-- Ports

port eventOutgoingPort : DTO -> Cmd msg

port eventIncomingPort : (DTO -> msg) -> Sub msg


-- PubSub

publish : Event -> Cmd msg
publish evt =
    outgoingEventPort (serialize evt)


subscribe : (Event -> msg) -> Sub msg
subscribe f =
    Sub.map f (incomingEventPort deserialize)

-- Serialization

serialize : Event -> DTO
serialize evt =
    case evt of
        SomethingHappened ->
          ("SomethingHappened", "")

        SomethingElseHappened int ->
            ("SomethingElseHappened", ... serialize int to json)


deserialize : DTO -> Event
deserialize ( key, json ) =
    case key of
        "SomethingHappened" ->
            SomethingHappened

        "SomethingElseHappened" ->
            SomethingElseHappened ... deserialize json to int


Dispatching an event looks like this:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        BlahMsg ->
            ( initialModel, Events.publish Events.SomethingHappened )

And subscribing to events looks something like this:

type Msg
    = Event Events.Event



subscriptions : Model -> Sub Msg
subscriptions model =
    Events.subscribe Event


I hope that makes sense.


On Thursday, July 21, 2016 at 2:30:30 PM UTC-4, OvermindDL1 wrote:
>
> I actually took your format and made it more generic:
> ```elm
> var app = Elm.Main.fullscreen();
>
> app.ports.*dispatchGlobal*.subscribe(function({portName, msg}) {
>     app.ports[portName].send(msg);
> });
> ```
> Where the dispatchGlobal would be:
> ```elm
> port *dispatchGlobal* : {portName : String, msg : Json.Encode.Value} -> 
> Cmd msg
> ```
> And the receiving could be about whatever you want:
> ```elm
> port *receiveSomeMessage* : ({something : Int, more : String} -> msg) -> 
> Sub msg
> ```
> Dispatching via a helper function like:
> ```elm
> dispatchSomeMessage =
>   dispatchGlobal {portName="receiveSomeMessage", (object [("something", 
> int 42), ("more", string "blah")])}
> ```
>
> Although I am using this style for a certain javascript callback library 
> that Elm does not support yet and not needed it to toss messages 'far' away 
> yet, and hope to not need to...
>
>
> On Thursday, July 21, 2016 at 12:01:26 PM UTC-6, Erik Lott wrote:
>>
>> Hey Aislan,
>>
>> Max's point of avoiding unnecessary components is a good one, but it 
>> depends on what scale of app/architecture you're talking about.
>>
>> When you're building building smaller types of UI components, it's a good 
>> rule to get you started. For example, let's say you want to build something 
>> simple like an html form in elm. You may want some input fields, select 
>> boxes, error messages, and maybe a custom submit button (whatever that is). 
>> This can likely be built within a single TEA component, without the need to 
>> create any additional subcomponents. Creating subcomponents for individual 
>> inputs, or special buttons, etc will likely be an unnecessary abstraction 
>> that will only make your code harder to understand, and harder to maintain. 
>> On the small scale, just avoid unnecessary componentization and you'll be 
>> fine.
>>
>> When you're building something at a larger scale like a single page app, 
>> that contains various layouts, menus, &  pages - which contain several 
>> components per page - you'll need components to keep your code organized, 
>> maintainable, and easy to understand. 
>>
>> The inter-component communication method that I posted at the top of this 
>> thread is likely only useful in a large app, where there's a need for app 
>> wide communication. Using this method for small scale parent-child 
>> communication probably overkill.
>>
>>
>>
>>
>> On Thursday, July 21, 2016 at 12:41:09 PM UTC-4, Aislan de Sousa Maia 
>> wrote:
>>>
>>> Hello guys! I'm a kind of noob with all of this. Can you explain a 
>>> little more the concern regarding componentization? Some examples could be 
>>> great. 
>>>
>>> Thanks for all!
>>>
>>

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to