4

I am attempting to follow this documentation to create a very simple bar graph, however, it seems as though Salesforce has no idea what is in my D3 static resource as it says ____ is not a function for anything I try to do with the imported D3 object.

I did exactly what the documentation said:

  • Went to D3's GitHub to download the resource files: https://github.com/d3/d3
  • Zipped the repo up
  • Created a new Static Resource and selected the d3-master.zip file as the file for the static resource.
  • Set the cache control to Public.

And then I went ahead and used this resource provided by D3 to construct a D3 Bar Chart.

I can't figure out what's wrong. I get errors for both D3.scaleLinear and D3.scaleBand functions when attempting to set y and x, respectively.

import { LightningElement } from 'lwc';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import D3 from '@salesforce/resourceUrl/D3';


export default class YtpReport extends LightningElement {
    svgWidth = 400;
    svgHeight = 400;

    d3Initialized = false;

    /**
     * Dummy Data Fillers
     */
    data = [
            {"name": "E", value: "10"},
            {"name": "A", value: "15"},
            {"name": "I", value: "25"},
            {"name": "Y", value: "9"},
            {"name": "U", value: "8"},
            {"name": "O", value: "3"}
        ]

    /**
     * Render the SVG
     */
    renderedCallback() {
        if (this.d3Initialized) {
            return;
        }
        this.d3Initialized = true;

        Promise.all([
            loadScript(this, D3 + '/d3.v5.min.js'),
            loadStyle(this, D3 + '/style.css'),
        ])
            .then(() => {
                this.initializeD3();
            })
            .catch(error => {
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Error loading D3',
                        message: error.body.message,
                        variant: 'error',
                    }),
                );
            });
    }

    /**
     * Calculations
     */
    y = D3.scaleLinear()
        .domain([0, D3.max(this.data, d => d.value)]).nice()
        .range([this.height - this.margin.bottom, this.margin.top])

    x = D3.scaleBand()
        .domain(this.data.map(d => d.name))
        .range([this.margin.left, this.width - this.margin.right])
        .paddingInner(0.1)

    xAxis = g => g
        .attr("transform", `translate(0,${this.height - this.margin.bottom})`)
        .call(D3.axisBottom(this.x).tickSizeOuter(0))

    yAxis = g => g
        .attr("transform", `translate(${this.margin.left},0)`)
        .call(D3.axisLeft(this.y))

    margin = ({top: 20, right: 0, bottom: 30, left: 40})

    /**
     * Initialize the data graph
     */
    initializeD3() {
        const svg = D3.select(this.template.querySelector('svg.d3'));
        //const width = this.svgWidth;
        //const height = this.svgHeight;

        svg.append("g")
            .attr("fill", "steelblue")
            .selectAll("rect")
            .data(this.data)
            .join("rect")
            .attr("x", d => this.x(d.name))
            .attr("y", d => this.y(d.value))
            .attr("height", d => this.y(0) - this.y(d.value))
            .attr("width", this.x.bandwidth());

        svg.append("g")
            .call(this.xAxis);

        svg.append("g")
            .call(this.yAxis);

        return svg.node();
    }

}

I even tried to copy exactly what they have in the documentation of showing a force-directed graph, and while I don't get any errors, I don't get any graph displayed.

2

You seem to have downloaded the source code for D3 from github. Whereas you only need the JS file and the CSS (as referenced in the documentation examples).

You can find the JS file on d3js.org, download it and then upload it as a static resource. If you also want to utilize the CSS as in the sample on documentation, then best place to download these files is on the lwc-recipe for this sample. Just download the files, zip it and upload it as static resource.

As an example, the static resource in my Org is named d3 and consists only of two files - the JS and the CSS. And based on the source code on lwc-recipes, the component is rendered perfectly fine (sample screenshot from my Dev Org).

enter image description here

  • So I download the d3.zip (github.com/d3/d3/releases/download/v5.9.1/d3.zip) file from D3's website, and only grab out the d3.min.js file and upload that? And if I want the css, I combine the d3.min.js with the style.css in a zip file and upload that instead? – BlondeSwan Feb 26 at 22:46
  • @BlondeSwan Yes, that's correct. You actually can utilize the one on the lwc-recipe link that I have provided. It provides you with those files. – Jayant Das Feb 26 at 22:47
  • Okay thanks. And then for a function like D3.scaleBand() that, according to this answer (stackoverflow.com/questions/38675348/…), I would need to get the d3-selection-multi.v1.min.js file and put into the zip file and re-upload the zip file into my static resources? – BlondeSwan Feb 26 at 23:00
  • @BlondeSwan I would imagine, yes. I haven't really worked with this library and know only in the context of the ones available in the samples. – Jayant Das Feb 26 at 23:01
  • Okay, so I used your link to get the right files, and I changed my code to be exactly the one that is in the documentation (both the JS and the HTML) and I don't get errors. but I don't get any graph appearing... Is there something I need to add in the HTML? – BlondeSwan Feb 26 at 23:03
1

After playing with this for a couple hours, it was the smallest thing to get it to cooperate.

I started by pulling down the entire lwc-recepies repo. Then I copied their d3 folder to my home directory and compressed (zipped) it into a .zip file, which I uploaded to Salesforce as a static resource.

I tried using the initialization routine for d3 from the lwc-recipes (here), but it did not work:

Promise.all([
  loadScript(this, D3 + '/d3.v5.min.js'),
  loadStyle(this, D3 + '/style.css')
]){... omitting the rest ... }

I found that I had to add d3 to the beginning of the file paths. Probably because the name of my zip file was d3. This is what I ended up using:

Promise.all([
  loadScript(this, D3 + 'd3/d3.v5.min.js'),
  loadStyle(this, D3 + 'd3/style.css')
]){... omitting the rest ... }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.