12

Is it manageable to using D3 with Elm using ports? I'm trying out Elm but I can't find any examples of using Elm with D3 without a wrapper API. The problem I've run into is that the wrapper and the forks don't work with 0.18. I'm also seeing a lot of statements that suggest building an API around javascript APIs is bad practice and that instead you should use ports. I can't find any examples of this with D3, however. I found this example but the D3 part was all done in plain javascript which doesn't really fit.

I'm probably being too aggressive with taking on D3 right off-the-bat with Elm but that's really what I want to do with it. If it's not really feasible to use D3 with Elm I'll probably not bother with it for now. Is there a fundamental problem with this kind of interaction or is it simply a lack of interest in D3 in the Elm community or am I just missing something?

For example, take this code ripped from the bl.ocks example above:

var t = d3.transition().duration(750);
var g = d3.select("svg g")
// JOIN new data with old elements.
var text = g.selectAll("text")
  .data(data, function(d) { return d; });

// ENTER new elements present in new data.
text.enter().append("text")
  .attr("class", "enter")
  .attr("dy", ".35em")
  .attr("y", -60)
  .attr("x", function(d, i) { return i * 24; })
  .style("fill-opacity", 1e-6)
  .text(function(d) { return d; })
  .transition(t)
  .attr("y", 0)
  .style("fill-opacity", 1);

Is there a straightforward translation into Elm for this kind of thing?

4
  • 1
    Here's an example of working with ports and a large JS library (google maps) simonh1000.github.io/2016/12/elm-ports-google-maps It might help you Commented Feb 15, 2017 at 16:30
  • @SimonH Thanks for your assistance. I've looked at some things like this but where I struggle is that d3 uses a lot of method references. You need to pass it functions and call functions on it that return functions (which are also objects). I'm clueless as to how to do this in Elm so that's where I was hoping to find a working (simple) example to start from. Commented Feb 15, 2017 at 17:58
  • Can you provide a code example of what you have to pass through the port. Expand your question to show what functionalty you want to access in D3 from Elm Commented Feb 15, 2017 at 18:46
  • @SimonH I added an example. Commented Feb 15, 2017 at 22:33

2 Answers 2

6
+50

I know only a little about D3. You will want to put all the data processing in Elm and just pass data out to the js code that controls D3. That will keep your model sane.

You also need to watch out for D3 mutating the DOM because then Elm will struggle to update the parts of the page it is responsible for. Best would be to carve up your page with elm parts and other parts using Elm.embed. But you might be able to have Elm write the whole page and let D3 mutate the DOM if you use Html.keyed to help Elm keep track of what is what in the DOM.

Html.keyed.div "d3node" 
  [ ]
  [ ... ensure that d3 only touches DOM elements inside this node ... ]

You cannot pass functions as such through a port, but you can pass json. so you might use elm to create something like

{ function_type: "f1",
  param1: ... ,
  param2: ...
}

Then you could in JavaScript do a

switch (data.function_type) of 
  case "f1: 
    function1 (data.param1, data.param2);
...


function1(p1, p2) {
  // some sort of D3 manipulation
  var text = g.selectAll(p1)
    .data(data, p2);
Sign up to request clarification or add additional context in comments.

3 Comments

So are the kinds of interactions with javascript in the example code not possible in Elm?
the problem is that the code you suggest mutates the DOM and that could confuse Elm's DOM updating. I'm not sure for certain and it might take trying ever to be sure. But using keyed will help
OK, that's helpful but what I really am looking for is help on how I can pass functions to D3 and how to retrieve functions/objects from D3 in order to pass them back to D3. The interop documentation for Elm that I have found seems to only talk about simple interactions. My preference (at least initially) is actually to do all presentation with D3. It can handle any DOM manipulation, not just SVG etc.
1

Your problem can be solved using a webcomponent like multi-chart.

Import the component inside index.html and create a node with the attributes you want:

Html.node "multi-chart" [ Html.Attributes.attribute "title" "test chart" ] []

4 Comments

I don't how this answers the question. Specifically, I'm not seeing anything with this project that relates to Elm.
What I wanted to point that in most cases the best way to do interop with javascript and Elm is not using ports but to use webcomponents. I learned from six months using Elm in production apps. Please check this talk from rtfeldman: youtube.com/watch?v=ar3TakwE8o0e
I guess I'm not sure how that helps me. I want to write the entire UI with D3. Business logic would be on the server. What's left that I would use Elm for?
If your entire UI is gonna be made in D3 using javascript, there is not much use for Elm. Elm is great when you want to have a very safe web UI, free from run time errors. The whole interop with javascript is thought around safety, but there is trade off between safety and ease to use. Maybe Elm is not good for this use case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.