Create a Chart with Code Block and D3 Library

Beside the Chart element that you can use to build charts, you can also use a combination of Code Block and javascript d3 library to create more customized data visualization.

The following link https://d3-graph-gallery.com/graph/barplot_horizontal.html showcases a basic horizontal bar chart from D3.js Graph Gallery, this tutorial will guide you on how can you use Code block to create a same plot in app builder.

  1. Load D3.js:

    • The Code Block element requires manually adding the D3 library to the document body using $script=document.createElement("script") and document.body.appendChild($script).

    • To ensure that the dependent code runs after the library is loaded, place the code inside $script.onload = function () { }.

  2. Set root ID and select by ID:

    • In the D3 gallery example, a div was created to contain the chart. However, in the Code Block element, we typically want the chart to be placed at the position of the Code Block element itself, allowing us to arrange it within the app builder. In order to do that, set the ID of the current Code Block element to "my_dataviz" using root.id = "my_dataviz".

    • When creating the SVG, use the same ID to select the Code Block element and create the SVG inside it: var svg = d3.select("#my_dataviz")

    • Remember to replace "my_dataviz" with your desired ID name.

  3. Write the remaining code in $script.onload = function () { }.

    • Within this block, you can write the custom code using the D3.js library to generate the desired chart.

    • Utilize the rich D3.js API and functions to create interactive and visually appealing data visualizations within the Code Block element.

Following these steps, we could create a chart in Code Block element same as the one in D3 gallary. Click preview to see the final result.

  1. Define event to enhance interaction(Optional).

    • Customized events allow you to pass data from within a Code Block to app or trigger other actions.

    • Using defineEvent() function, fill title, name and event to define an event in Code Block. Note that it should be defined outside render function

    • Setup trigger to emit the event.

    • The new defined event will appear in the Code Block's interaction panel. Use it to create Interactions

    • To be more specific, if you want to define a barclick event, try:

      defineEvent(/* event definition */ {
          title: "Click",
          name: "barclick",
          payload: [
              {
                  name: "Country",
                  field: "country",
                  type: "string"
              },
              {
                  name: "Value",
                  field: "value",
                  type: "number"
              }
          ]
      })
    • And add add .on("click", function (event, d) { console.log([event,d]) emit('barclick', { country: d.Country, value: d.Value}); }); at the end of the svg.append command.

Source code in Code Block

function setupCode({ emit, defineEvent, defineMethod, console }, dependencies) {
    function render(data, { root, rendered, props, getThemeValue }) {
        // Set the ID of the current Code Block element to 'my_dataviz'
        root.id = "my_dataviz"

        // Load d3.js library
        const $script = document.createElement('script');
        document.body.appendChild($script);
        $script.src = "https://d3js.org/d3.v6.min.js";

        // When the D3.js script has loaded, execute the following code.
        $script.onload = function () {
            {
                d3.select('#my_dataviz').selectAll('svg').remove();
                // Select current Code Block by its id 'my_dataviz', then create a new SVG element with a width and height of 400
                // set the dimensions and margins of the graph
                // set the dimensions and margins of the graph
                const margin = { top: 20, right: 30, bottom: 40, left: 90 },
                    width = 400 - margin.left - margin.right,
                    height = 400 - margin.top - margin.bottom;

                // append the svg object to the body of the page
                const svg = d3.select("#my_dataviz")
                    .append("svg")
                    .attr("width", width + margin.left + margin.right)
                    .attr("height", height + margin.top + margin.bottom)
                    .append("g")
                    .attr("transform", `translate(${margin.left}, ${margin.top})`);

                // Parse the Data
                d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/7_OneCatOneNum_header.csv").then(function (data) {

                    // Add X axis
                    const x = d3.scaleLinear()
                        .domain([0, 13000])
                        .range([0, width]);
                    svg.append("g")
                        .attr("transform", `translate(0, ${height})`)
                        .call(d3.axisBottom(x))
                        .selectAll("text")
                        .attr("transform", "translate(-10,0)rotate(-45)")
                        .style("text-anchor", "end");

                    // Y axis
                    const y = d3.scaleBand()
                        .range([0, height])
                        .domain(data.map(d => d.Country))
                        .padding(0.1);
                    svg.append("g")
                        .call(d3.axisLeft(y))

                    //Bars
                    svg.selectAll("myRect")
                        .data(data)
                        .join("rect")
                        .attr("x", x(0))
                        .attr("y", d => y(d.Country))
                        .attr("width", d => x(d.Value))
                        .attr("height", y.bandwidth())
                        .attr("fill", "#69b3a2")
                        .on("click", function (event, d) {
                            console.log([event, d])
                            emit('barclick', { country: d.Country, value: d.Value });
                        });

                })

            }
        }
    }

    defineEvent(/* event definition */ {
        title: "Bar Click",
        name: "barclick",
        payload: [
            {
                name: "Country",
                field: "country",
                type: "string"
            },
            {
                name: "Value",
                field: "value",
                type: "number"
            }
        ]
    })

    return { render };
}

Last updated