Is it possible to add an external graph, created for example with D3.js, to my dashboard?

plotly.js is actually its own thing that uses some of D3.js and webgl to render plots. The key thing in plotly.js is that its API is declarative and JSON based, which makes it portable in other languages like Python and relatively easy to wrap inside React. Here’s the source for how I wrap plotly.js into a React component: https://github.com/plotly/dash-core-components/blob/b7f776f4aa15be3dae160a4df7b011a4eaa7f425/src/components/Graph.react.js

To create a react version of a d3 graph, you’ll need to convert your d3 code into some type of stateless function that renders a graph based off of a JSON object. Here’s a contrived example based off googling https://bl.ocks.org/mbostock/3883245. This code is just a sketch, I have not tested this myself, I’m mostly just copying and pasting.

function LineGraph(divSelector, xData, yData, xTitle, yTitle, color) {

    var svg = d3.select(divId),
        margin = {top: 20, right: 20, bottom: 30, left: 50},
        width = +svg.attr("width") - margin.left - margin.right,
        height = +svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var parseTime = d3.timeParse("%d-%b-%y");

    var x = d3.scaleTime()
        .rangeRound([0, width]);

    var y = d3.scaleLinear()
        .rangeRound([height, 0]);

    var line = d3.line()
        .x(function(d) { return x(xData); })
        .y(function(d) { return y(yData); });

    g.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x))
    .select(".domain")
      .remove();

    g.append("g")
      .call(d3.axisLeft(y))
    .append("text")
      .attr("fill", "#000")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", "0.71em")
      .attr("text-anchor", "end")
      .text(yTitle;

      g.append("path")
          .datum(data)
          .attr("fill", "none")
          .attr("stroke", color)
          .attr("stroke-linejoin", "round")
          .attr("stroke-linecap", "round")
          .attr("stroke-width", 1.5)
          .attr("d", line);
    });

}

Then, your Dash-compatible react component could be as simple as:

class LineGraph extends Component {
    constructor() {
        super();
        this.plot = this.plot.bind(this);
    }
    plot(props) {
        LineGraph(
            props.id,
            props.xData,
            props.yData,
            props.xTitle,
            props.yTitle,
            props.color
        );
    }

    componentDidMount() {
        this.plot(this.props);
    }

    componentWillReceiveProps(newProps) {
        this.plot(newProps);
    }

    render() {
        return <div id={props.id}/>
    }
}

LineGraph.propTypes = {
    id: PropTypes.string,
    xData: PropTypes.array,
    yData: PropTypes.array,
    xTitle: PropTypes.array,
    color: PropTypes.string
}

Which would then be accessible in Dash with something like:

import CustomComponents
CustomComponents.LineGraph(
    xData=df['some-column'],  # Dash converts dataframe columns to json for you
    yData=df['another-column'],  # Dash converts dataframe columns to json for you
    xTitle='my title',
    color='steel blue'
)

For reference, here is the way that plotly.js describes all of the different attributes of charts: https://plot.ly/python/reference. These attributes are accessible inside the figure property of the dcc.Graph component.

2 Likes