john mangual john mangual - 6 months ago 18
Javascript Question

Trouble Connecting Ports and Subscriptions

I am reading through the Elm guide and their JavaScript interOp. Here is a simplified version:

port module FooBar exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.App as Html
import String

main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}

-- subscriptions
port f : () -> Cmd msg
port g : ( Int -> msg ) -> Sub msg

subscriptions: Model -> Sub Msg
subscriptions model = g Get

-- MODEL
type alias Model = { pt : Int }

-- VIEW
view: Model -> Html Msg
view model = Html.text ( toString model.pt )

-- UPDATE
type Msg = Ask | Get Int

update: Msg -> Model -> (Model, Cmd msg)
update msg model =
case msg of
Ask -> (model, f () )
Get x -> ( Model x, Cmd.none )

-- INIT
init: (Model, Cmd Msg)
init = ( Model 0, f ())


The App is initially set to 0 but it should read the message from JavaScript and be set to 1. However, it remains at 0. Are the Elm ports set up properly?





<div id="foobar"></div>
<script src="foo.js"></script>
<script>
var node = document.getElementById("foobar");
var app = Elm.FooBar.embed(node);

app.ports.f.subscribe(
function(){
var myValue = 1;
console.log(myValue);
app.ports.g.send(myValue);
}
);
</script>

</body>


Here I put:
elm-make foo.elm --output=foo.js


The fact that
myValue
prints to console as 1 suggests the
f()
port got called, but the
g()
port never gets sent back or handled properly.

Answer

Hard to tell if this is a design decision, but init is called before Html.App is subscribed to any ports.

Therefore calling f () from init will have no effect.

I use send function, which runs a dummy task and always sends Ask message, which will trigger the outgoing port.

Consider changing your init to send a message, that sends the data to the port:

-- INIT


init : ( Model, Cmd Msg )
init =
    -- ( Model 0, f ())
    ( Model 0, send Ask )


send : msg -> Cmd msg
send msg =
  Task.perform identity identity (Task.succeed msg)
Comments