I have been working with a framework using mithril.js and wish to add this script that draws an interactive tree into a component on my website.
So far, I just placed the JS code inside the script
tags into my application, and I know that normally, the DOM object generated is obtained by calling svg.node()
. But I know I can’t return that from my object’s view
method, and instead need to return something of the form m(...)
. I tried looking at sources like this one but couldn’t find a solution to my problem in them. Is there a known way for incorporating D3 SVG graphics into mihtril.js?
If you wanted to look at the code I have right now:
export default class TreeModal extends Modal { content() { var treeData = ... // some data ... // Other code; irrelevant to this question var svg = d3.select("body").append("svg") .attr("width", width + margin.right + margin.left) .attr("height", height + margin.top + margin.bottom).append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // Some other code adding more functionality // At this point, svg contains the SVG object which I wish to display return svg.node(); // Raises ILLEGAL CONSTRUCTOR error; how to adapt this for Mithril.js? } }
Thanks in advance for all the help!
UPDATE: It seems like what a Modal
is is crucial to my problem, because the API I use actually asks me to implement the content()
method in any subclasses of Modal
. I looked in Modal.js
, and the relevant bit is:
export default class Modal { view() { return ( <div> ... {this.content()} ... </div> ) } }
Ideally, the solution would not have to override the view()
method of Modal
and only would include changes to content()
in TreeModal
.
Advertisement
Answer
It is really hard to write correct code without knowing the implementation or documentation of the base Modal class. To work around the API you have mentioned we can render a div in content with a random id that we use later to find it after it is placed into the DOM tree. Then inject the SVG into that div and use D3 as you normally would. I’m not sure if D3 needs cleanup but that would be done in onremove
, again make sure to call the parents onremove
if necessary.
I use JSX in content
but I wasn’t able to test its format.
export default class TreeModal extends Modal { constructor() { // @TODO: Not sure what Modal's constructor looks like. super(); // Create a random DOM id we share between content() //and oncreate(). this.svgContainerId = 'svg_container_' + Math.floor(Math.random()*1000000000) + 1; } oncreate(vnode) { // @TODO: Check if Modal implements this method or not. // super.oncreate(vnode); var treeData = {} // some data ... // Other code; irrelevant to this question // USE our predefined id to lookup the div rendered in content // and inject our SVG into that container. var svg = d3.select(document.getElementById(this.svgContainerId)).append("svg") .attr("width", width + margin.right + margin.left) .attr("height", height + margin.top + margin.bottom).append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // Some other code adding more functionality } content() { // render a plain DIV with our predefined id that never changes. // this JSX is untested return (<div id="{this.svgContainerId}"/>); } }