1

I have developed a Lightning Web Component using Chartjs according to the example given here: https://github.com/trailheadapps/lwc-recipes/tree/master/force-app/main/default/lwc/libsChartjs

I have added the ability to bring in retrieved data as the dataset, and to generate a new chart when the dataset is changed. However, the line that creates the chart does so by appending to the existing DOM: this.template.querySelector('div.chart').appendChild(this.canvas);

I want to have the chart be replaced when the dataset changes. I have looked at the Chartjs options, and it would seem that I could use chart.reset() or chart.update() to update the existing data, but there does not seem to be a way in LWC to replace the chart with the new chart rather than appending it (showing all rendered charts).

Is there a way to "wipe clean" the DOM/HTML before appending the new chart? Or is there a way to replace the chart in the existing DOM without appending it? I have been working on this for a couple of days now and I cannot see how to do it. Even a way to completely re-render the component from scratch each time may work, but I cannot figure out how to do that either.

So, my component subscribes to a change in another component that sends an account code. When the account code changes, I retrieve numerical information related to that account code and create a chart with that data. I want the component to only show the latest chart, not append the chart to the existing chart that was last shown. I also thought that maybe I could store the charts in a list, and only display the last one, but I would have to re-render the DOM entirely to make that work as well.

Any help is appreciated. This is the last logistical hump to get over to create a Lightning App Page that I have been asked to do.

EDIT: After much research, it seems there is no way to affect the existing DOM. When I try to do a RemoveChild(), I get an error about access being denied from namespace "c". I cannot imagine that there is NO way to refresh a chart in Lightning Web Components when new data is received. Once again...any help is appreciated.

1

Normal HTML applies here; you can just remove the element:

const chartContainer = this.template.querySelector('div.chart');
while(chartContainer.firstChild) {
  chartContainer.removeChild(chartContainer.firstChild);
}
chartContainer.appendChild(this.canvas);

Or, instead of dumping the old canvas, you could clear the canvas and draw anew.

const context = this.canvas.getContext('2d');
context.clearRect(0, 0, this.canvas.width, this.canvas.height);
| improve this answer | |
  • Trying the first logic gives me the following error in the Lightning App Page: Access denied: {"from":{"namespace":"c"}}. Going to try the second logic now. – Jonathan May 6 at 16:16
  • The second logic does not work - the subsequent charts still get appended. I think it is because clearing the context does not change the chart that has already been appended to the DOM. It clears the context that is about to be added, but that was happening anyway. The problem is that when the second chart is being generated, there is no way to reference the area where the first chart is. That is why I want to completely recreate the DOM in the component when the chart is re-rendered with new info. – Jonathan May 6 at 16:28
  • If there was a way to display the chartContainer in the DOM, and then refresh the value of that container, that could work...but in order to use appendChild, the template needs to be empty, and I cannot figure out which variable I can display in the template to get this to work. Something like "chart.display", if such a thing existed. – Jonathan May 6 at 16:30
  • If the ChartJS elements are giving you trouble because of the way the components handle DOM access, would wrapping the Chart in an LWC and making that LWC a child of your current component work? It should be possible to add and remove LWCs. – nbrown May 6 at 16:33
  • Interesting...I was just pursuing something like this...but I do not know how to "destroy" child LWCs from the parent. Still researching... – Jonathan May 6 at 18:44

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.