When refreshing data, duplicate the d3 graph

When I try to update my d3 graph after selecting a site from the dropdown menu, a new graph is generated and I can't figure out how to remove the old one.

https://i.sstatic.net/R5BNE.png

Below is the code within the script tags:

<script>

import * as d3 from 'd3'
import { rgbaToHex } from '../utils/color.ts'

export default {
  data () {
    return {
      selectedSite: '',
      selectedWhale: '',
      groupType: '',
      heatmapShow: false
    }
  },
  mounted () {
    this.generateChart()
  },
  methods: {
    generateChart () {
      // set the dimensions and margins of the graph
      const margin = { top: 20, right: 20, bottom: 30, left: 30 }
      const width = 1850 - margin.left - margin.right
      const height = 200 - margin.top - margin.bottom

      // create an area for the graph
      const svg = d3.select('#heatmap')
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', `translate(${margin.left}, ${margin.bottom})`)
        
      // define x and y labels
      const xLabel = d3.range(259)
      const yLabel = d3.range(23, -1, -1)

      const x = d3.scaleBand()
        .domain(xLabel)
        .range([0, width])
        .padding(0.05)

      svg.append('g')
        .attr('transform', `translate(0, ${height})`)
        .call(d3.axisBottom(x).tickValues(x.domain().filter((_, i) => !(i % 6))))

      const y = d3.scaleBand()
        .domain(yLabel)
        .range([height, 0])
        .padding(0.05)

      svg.append('g').call(d3.axisLeft(y).tickValues(y.domain().filter((_, i) => !(i % 5))))

      d3.json('../predictions.json').then((data) => {
        const u = svg.selectAll().data(data.heatmaps[this.selectedWhale][this.selectedSite])

        u.exit().remove()

        const uEnter = u.enter().append('rect')

        uEnter
          .merge(u)
          .transition()
          .duration(1000)
          .attr('x', function (d) {
            return x(d[1])
          })
          .attr('y', function (d) {
            return y(d[0])
          })
          .attr('cx', 1)
          .attr('cy', 1)
          .attr('width', x.bandwidth())
          .attr('height', y.bandwidth())
          .style('fill', function (d) {
            return rgbaToHex(0, 128, 255, 100 * d[2])
          })
          .on('mouseover', function () {
            d3.select(this)
              .style('stroke', 'black')
              .style('opacity', 1)
          })
          .on('mouseout', function () {
            d3.select(this)
              .style('stroke', 'none')
              .style('opacity', 0.8)
          })
          .on('click', (d) => {
            console.log(d)
            this.heatmapShow = true
          })

        uEnter.exit().remove()
      })
    }
  },
  watch: {
    selectedSite: function () {
      this.generateChart()
    },
    selectedWhale: function () {
      this.generateChart()
    },
    groupType: function (value) {
      console.log(value)
    }
  }
}
</script>

Answer №1

It seems like you're using the ID to designate where you want your graph canvas to go, but you're appending it instead of inserting a new one.

selection.append(type)

If the specified type is a string, it adds a new element of this type (tag name) as the last child of each selected element, or before the next following sibling in the update selection if this is an enter selection.

For more information, visit here.

Consider removing the ID before repainting it using selection remove and then try appending/inserting it again.

Answer №2

To address the issue, I followed the suggestion given earlier and included d3.select('svg').remove() before redefining the svg const.

      const margin = { top: 20, right: 20, bottom: 30, left: 30 }
      const width = 1850 - margin.left - margin.right
      const height = 200 - margin.top - margin.bottom

      d3.select('svg').remove()

      // setting up the graph area
      const svg = d3.select('#heatmap')
        .append('svg') // the svg element can contain titles and color scales

      /* remainder of the script */

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Javascript to dynamically enable or disable an input field depending on the choice made in another field

I attempted to implement the solution provided in this answer for my code: How do I disable input field when certain select list value is picked but unfortunately, it is not working as expected. The scenario involves an HTML select field with the ID &apos ...

While executing a jssor code in SP 2007, IE experiences freezing issues

I've integrated a jssor slider with vertical navigation (without jQuery) into a Sharepoint 2007 page using CEWP. All the image links have been replaced with images stored in the SP image library, and the jssor.slider.min.js file has been uploaded to t ...

Where am I going wrong in my attempts to use a callback function?

I am currently attempting to implement a callback function for this particular JavaScript function. function Filtering_GetSite(siteElement) { $.ajax({ type: "POST", url: "samle.asmx/f1", data: "", contentType: "application/json; charset= ...

The jqGrid displays a plus sign even when the subgrid is empty while using XML

I am utilizing jqGrid to display data with a subgrid in XML format. $("#UDFs").jqGrid({ ajaxGridOptions: { contentType: 'application/xml; charset=utf-8' }, datatype: 'xmlstring', datastr: data, xmlReader: { root: "Respo ...

issue encountered when filling out a dropdown menu using a JSON data structure

Seeking assistance with populating a button dropdown in angularjs. Encountering the error message: "Unexpected end of expression: data.WotcSummary "|. Any ideas on what might be causing this issue? Here is the JavaScript file code snippet: WotcDashBoard ...

Utilizing TypeScript to Populate an observableArray in KnockoutJS

Is there a way to populate an observableArray in KnockoutJS using TypeScript? My ViewModel is defined as a class. In the absence of TypeScript, I would typically load the data using $.getJSON(); and then map it accordingly. function ViewModel() { var ...

What is the process for transitioning data between SQL, PHP, and JavaScript seamlessly?

As a developer who frequently works on SQL/PHP applications, I often find myself constantly rewriting JavaScript code to accomplish the same tasks repeatedly. When dealing with simple APIs, it's not too difficult to create one-off AJAX methods to comm ...

Ways to change object to string in javascript

My object has the following structure: Object {Dry Aged Ribeye(medium): "1" , Dry Aged Ribeye(rare): "1" , Dry Aged Ribeye(well): "1" , favorite_tables: "{"dc76e9f0c0006e8f919e0c515c66dbba3982f785":[]}" } I am trying to insert this into My ...

Creating a Website for Compatibility with NoScript

During my journey of building a nameplate site from the ground up for myself, I have delved into the realms of learning and establishing my online presence. The highlight of my project is a sleek tabbed site that employs AJAX and anchor navigation to seaml ...

Unable to understand the reason behind why the button is not being displayed

I'm having trouble with my quiz app. I have a button to submit answers and move on to the next question, but whenever I try to place it within the div that contains the quiz, the button disappears. Can someone please help me figure out what's wro ...

Utilize the function of express

The following code is not behaving as expected: var express = require('express'); var app = express(); app.use(function(req, res, next) { console.log('first statement'); next(); }, function (req, res, next) { console.log('se ...

Leveraging dynamic slots and dynamic components

I am currently developing a MultiStepForm component and aiming to make it as dynamic as possible. In my Setup.vue component, I have defined a steps array structured like this: const steps = ref([ { label: 'Company', number: 1, ...

Exploring the functionalities of MongoDB through Populate, Aggregate, and Un

My user model contains the following data structure: { _id: object, name: string, quotes: [ { quote: string, createdAt: date } ], friends: [ { _id: object } ] (referring to the _id from the user model) } My goal is to extract and return the following ...

NodeJS Express REST API fails to fetch data in GET request

As I work on developing a REST API using NodeJS and Express, I have set up routes for handling "offers". However, when attempting to send a GET request, I receive an empty response along with a 200 status code. Here is the snippet from routes.js: route ...

Optimizing the display of multiple list items using Javascript for two separate UL elements on a single webpage

How can I display a maximum of 5 list items in two separate UL elements on the same page and hide the rest? Users should be able to see more items by clicking a dynamic "See more" element created by JavaScript. Below are the UL elements I want to work wit ...

What is the process for incorporating a Bootstrap link into a specific ReactJS file?

In my current project using React JS, I found the need to incorporate Bootstrap in certain pages. To do this, I initially placed the following code snippet in the Public folder within index.html: <link rel="stylesheet" href="https://netdna.bootstrapc ...

Remove the JSON key from all array elements while preserving their child elements

I have an array of JSON objects that looks like this: var array_json = [{"my":{"id":144,"price":12500000}}, {"my":{"id":145,"price":13500000}},{"my":{"id":146,"price":13450000}}, {"my":{"id":147,"price":11500000}},{"my":{"id":148,"price":15560000}}] My g ...

There seems to be an issue with $(window).scrollTop() not functioning properly in Safari

While it works smoothly on Firefox and Chrome, there seems to be an issue with Safari. Here is the code snippet: function founders() { var scrollPos = $(window).scrollTop(); if (scrollPos == 900) { $(function() { $(".first_fall").f ...

The Jquery validation in Asp.Net MVC 5 does not seem to work properly when using ajax post during a submit event, as it incorrectly

I've double-checked all the necessary elements for client-side validation, but unfortunately, the validation is still not working. I would greatly appreciate it if someone could assist me in identifying what I might have overlooked or where I may hav ...

Search in the Firestore database for documents that have a field containing a reference to another document. Once those results are found, use the reference to conduct a second query

In an attempt to optimize the query that delivers details of all events a participant has attended, I have restructured my database schema. Events with participants are now linked through a subEvent subcollection in the users collection, storing document r ...