10

I need to pass a few parameters to Javascript, but for a strange reason it does not compile. I started with:

port check : String -> Cmd msg

this works fine (as taken directly from JavaScript Interop). But when I am adding another parameter

port check : Int -> String -> Cmd msg

I am getting

1| port check : Int -> String -> Cmd msg
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You are saying it should be:

Int -> String -> Platform.Cmd.Cmd msg

But you need to use the particular format described here: http://guide.elm-lang.org/effect_managers/

I solved this simply by reducing arguments back to one

type alias Bundle = (Int, String)
port check : Bundle -> Cmd msg

but that would be cleaner if I could simply do

app.ports.check.subscribe(function(arg1, arg2) {
});

Why it doesn't compile?

Lukasz Guminski
  • 862
  • 7
  • 20
  • I don't know for certain but in earlier Elm versions, ports took a Signal of (a Signal.map of) a model, so were used with records (JS objects). Perhaps, as a result, thay have always only passed a single argument – Simon H Aug 28 '16 at 16:11

2 Answers2

17

ports can only have one parameter. If you need to pass multiple parameters then your only options are to pass a tuple (like you did with Bundle) or a record.

On the js side, you'll have to take one parameter but you can destructure it after with whatever var names you want

app.ports.check.subscribe(function(arg) {
  var [arg1, arg2] = arg;
});

If you're using ES6, then you do have some nicer options for destructuring in the function params if you use a record like this:

app.ports.check.subscribe(function({arg1: arg1, arg2: arg2}) {
});
robertjlooby
  • 7,160
  • 2
  • 33
  • 45
  • I noticed that only one parameter gets accepted, but why? On Javascript side I already "deserialized" the arguments like you suggested, but I wonder why Elm cannot accept more parameters. It look like a bug to me. Clearly an inconsistency. – Lukasz Guminski Aug 28 '16 at 20:40
  • I don't think it's a bug. Isn't that just because the type Cmd takes one parameter? http://package.elm-lang.org/packages/elm-lang/core/4.0.5/Platform-Cmd#Cmd – Rafał Cieślak Sep 02 '16 at 16:17
  • @RafałCieślak ok. I think I understand now how it works. Thanks. Still I am not sure if this is the correct behavior. The need for wrapping and unwrapping makes me uncomfortable. – Lukasz Guminski Sep 03 '16 at 16:05
8

I noticed you don't really have to "decode" much on the Javascript side. So, you can package your single parameter up as a nice type in ELM.

Do something like this in your elm:

type alias MyObject = 
  { name: String 
  , displayDate: String
  , subTitle: String
  , hashTag: String
  }

port check : MyObject -> Cmd msg 

Then in the javascript you can just do this:

app.ports.check.subscribe(function(myObject) {
            alert( myObject.name);
            alert( myObject.displayDate);
            alert( myObject.subTitle);
            alert( myObject.hashTag);
        });
user7106980
  • 81
  • 1
  • 1