Hi,
I’m starting a new elm project (0.19) and am having a problem setting up ports out to JS. I have other projects that use ports fine, so this is driving me a little crazy… although it’s my first time using Browser.application so maybe I’m missing something.
I’ve stripped out Main.elm to be just a port module using the simple counter example - which compiles and functions as it should.
However, when I try and reference a port method on the JS side, I get:
TypeError: undefined is not an object (app.ports.cache)
If I change init
from
init : Value -> Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url navKey =
( 0, Cmd.none )
to call the port function
init : Value -> Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url navKey =
( 0, cache "" )
then all is good, the cache
port gets called on the JS side, and logging the port object to the console reports what would be expected: an object (cache
) with subscribe
and unsubscribe
functions.
Why do I appear to need to call the port function (cache
) in init
in order to have access to the port on the JS side?
What am I missing (doing wrong)?
Thanks
Code below:
ELM:
port module Counter exposing (main)
import Browser
import Browser.Navigation as Nav
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
import Json.Decode exposing (Value)
import Url exposing (Url)
port cache : String -> Cmd msg
-- MODEL
type alias Model =
Int
init : Value -> Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url navKey =
( 0, Cmd.none )
-- UPDATE
type Msg
= Increment
| Decrement
| Reset
| ChangedUrl Url
| ClickedLink Browser.UrlRequest
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Increment ->
( model + 1, Cmd.none )
Decrement ->
( model - 1, Cmd.none )
Reset ->
( 0, Cmd.none )
ChangedUrl _ ->
( model, Cmd.none )
ClickedLink _ ->
( model, Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- VIEW
view : Model -> Browser.Document Msg
view model =
{ title = "Counter"
, body =
[ div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (String.fromInt model) ]
, button [ onClick Increment ] [ text "+" ]
, button [ onClick Reset ] [ text "reset" ]
]
]
}
-- MAIN
main : Program Value Model Msg
main =
Browser.application
{ init = init
, onUrlChange = ChangedUrl
, onUrlRequest = ClickedLink
, subscriptions = subscriptions
, update = update
, view = view
}
JS:
var elmAppContainerId = 'elm-app-container'
var elmAppContainer = document.getElementById(elmAppContainerId)
if (elmAppContainer)
{
var app = Elm.Counter.init({node: elmAppContainer, flags: {}})
console.log(app.ports) // undefined
app.ports.cache.subscribe( function() { console.log("Cached" );} ); // Results in a TypeError
}
else
{
console.log("Can't find element with ID: " + elmAppContainerId)
}