1

I'm trying to find the best way to execute some javascript as part of my view function. In the view function I want to create a canvas object and then execute a native function that inserts some data into it based on my model. The parts individually seem easy enough to write, but I'm not sure how to glue them together.

If I simply insert the native call into my view code, presumably it has to produce some HTML (e.g. an empty div) in order to satisfy the type system; perhaps this is the correct thing to do, but it feels a bit hackish. Is there a better, more idiomatic way? Am I even thinking about this in the correct, Elm-ish way?

abingham
  • 1,294
  • 1
  • 10
  • 17
  • FWIW, this is in an attempt to use ChartJS. I know there are existing libraries that do this, but they have problems, seem abandonded, or aren't otherwise usable. And in any event I'd like to understand how to do it as a learning exercise. – abingham Feb 12 '16 at 09:21
  • You need to pipe your data out via a port and pick it up in javascript - see http://elm-lang.org/guide/interop. Up to you whether you create the div to contain the chart in your html or have Elm do it – Simon H Feb 12 '16 at 13:54
  • By blog http://simonh1000.github.io/2015/10/elm-architecture-ports/ might also give you some ideas, even if it is about google maps rather than chartjs. – Simon H Feb 12 '16 at 13:58
  • Ports seemed like the right answer, but since they can only be defined in the main file how can a reusable module be written to use them? How can my module's native code know the name by which to refer to the port that the data would come in through? – abingham Feb 12 '16 at 14:02
  • 1
    You can't write in Elm a self-standing module with its own local data. There are repeated discussions about this on the mailing list. Supposedly 0.27 is going to help a bit, but Evan's vision is of a single state – Simon H Feb 12 '16 at 14:05
  • That seems strangely (and somewhat arbitrarily) at odds with the mantras of modularity and "fractal design" I keep seeing in Elm discussions. But if that's how it is, that's how it is. – abingham Feb 12 '16 at 14:11

1 Answers1

1

The best way I have found is to create a Mailbox for this in the main module:

messageMailbox : Signal.Mailbox String
messageMailbox =
    Signal.mailbox ""

Then create a port to listen to the signal from that mailbox:

port messsagePort : Signal String
port messsagePort =
    messageMailbox.signal

In Js you subscribe to this port:

app.ports.messsagePort.subscribe(function (args) {
    ...
})

Then you send a message to this mailbox either from your view or your update function (as an effect in case of update):

Signal.send messageMailbox.address message
Sebastian
  • 2,249
  • 17
  • 20