What is the best way to combine Vue and d3 to build a reusable component?

I am in the process of developing a Chart.vue component using D3. My goal is to have the ability to add multiple instances of this component to a single page while ensuring that each instance remains separate.

In my attempt to achieve this, I decided to assign a unique ID generated with uuid to the div surrounding my component in the template:

<template>
  <div :id=this.id>
    <svg></svg>
  </div>
</template>

The ID is dynamically created when the component is initialized.

<script>
import * as d3 from "d3";
import { v4 as uuidv4 } from "uuid";

export default {
  ...
  created () {
    this.id = uuidv4()
  }, 
  ...

Whenever there is an update to the data passed in as props from the parent component App.vue, the chart is re-rendered. To pinpoint the specific <svg> element associated with each instance of the Chart component, I leverage the unique this.id in my renderChart method:

  methods: {
    renderChart(chart_data) {
      const svg_width = 1000;
      const svg_height = 600;
  
      const svg = d3
        .select("#" + this.id)
        .select("svg")
        .attr("width", svg_width)
        .attr("height", svg_height);
      ...

This is followed by the addition of axes, data, and other necessary components.

Upon adding two instances of the Chart component to my App.vue template:

<template>
  <div id="app">
    <form action="#" @submit.prevent="getIssues">
      <div class="form-group">
        <input
          type="text"
          placeholder="owner/repo Name"
          v-model="repository"
          class="col-md-2 col-md-offset-5"
        >
      </div>
    </form>
    <Chart :issues="issues" />
    <Chart :issues="issues" />
  </div>
</template>

Both instances are appended to the DOM with distinct uuid values. However, during the execution of the renderChart function after updating the data, only one chart is visible instead of two.

As someone new to JavaScript, Vue, and D3, I may be approaching this incorrectly. It appears as though my approach should work, but any guidance would be greatly appreciated.

Answer №1

After much trial and error, I stumbled upon a solution that while effective, remains somewhat mysterious to me. The initial approach I took seemed promising at times, but the results were always unpredictable.

To make it work, I began passing a distinct ID from the parent template to the component as a prop, which I then incorporated into the Chart component's <div> id tag.

This is how it looks in App.vue:

<template>
  <div id="app">
    <form action="#" @submit.prevent="getIssues">
      <div class="form-group">
        <input
          type="text"
          placeholder="owner/repo Name"
          v-model="repository"
          class="col-md-2 col-md-offset-5"
        >
      </div>
    </form>
    <Chart id="chart1" :issues="issues" />
    <Chart id="chart2" :issues="issues" />        
  </div>
</template>

Next step was to include id in the props of Chart.vue and define a variable within the data() section.

<template>
  <div :id=chart_id>
    <svg></svg>
  </div>
</template>

<script>
import * as d3 from "d3";

export default {
  name: 'Chart',
  props: ["issues", "id"],
  
  data() {
    return {
      chart: null,
      chart_id: this.id
    };
  },
  ...

For reasons unknown, the uuid method failed me, but this new approach feels more reliable and secure.

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

I am facing difficulty transitioning from iframe to the Angular App

I have attempted various solutions from stack overflow to switch to an iframe using ProtractorJS, but none of them have successfully worked for me. I am seeking help from someone who has faced a similar issue and could provide some guidance. The Issue: Wh ...

Tips for combining two htmlelements together

I have two HTML table classes that I refer to as htmlelement and I would like to combine them. This is similar to the following code snippet: var first = document.getElementsByClassName("firstclass") as HTMLCollectionOf<HTMLElement>; var se ...

Experiencing a No data error when attempting to confirm Authentication using passkey with SimpleWebAuthn in conjunction with Node.js and react.js

I am currently implementing passkey login functionality in my react.js app with a node.js backend and MongoDB database. Below is the code snippet for the backend: const registerWebAuthentication = async (req, res) => { // Backend code for registering ...

What is the prescribed interface or datatype for symbol type in TypeScript with JavaScript?

I have a set of symbol values in JavaScript that I want to convert to TypeScript. // Defining object values in JavaScript const size = { Large: Symbol('large'), Medium: Symbol('medium') } What is the most efficient method to conv ...

A guide to activating double and single click functionality for GridView rows in Asp.net using C#

I have a GridView row in Asp.net and currently have a single click event working on it. However, I now require a Double Click event for my Grid rows. Can anyone provide guidance on how to achieve this? Your assistance is greatly appreciated. ...

tips on assigning a unique ID to an item in a firebase database collection

My code is structured like this: const userCollectionRef = collection(db, 'users'); Then I add data using the following method : const addInfoToDataBase = async () => { checkLike(); await addDoc(userCollectionRef, { likePost: us ...

What is the process for saving selected values from a drop-down list into a database?

Hey there, I'm a newcomer to PHP and ajax. When choosing an option from the drop-down list, a separate div function should appear where I need to insert both the selected option and input data in different divs. Sorry for my poor English. Any help fro ...

Guide on Crafting an Interactive Breadcrumbs Component

How can I implement product category breadcrumbs on the product page? These breadcrumbs will represent the parent category of the product. I am utilizing Next.js and Strapi for this project. For example, here is a screenshot showing how it should look: ...

Assigning alphanumeric characters to the axis for identification purposes

review the code in index.html <!DOCTYPE html> <html> <head> <title>D3 test</title> <style> .grid .tick { stroke: lightgrey; opacity: 0.7; } .grid path { stroke-width: 0; } .ch ...

Talebook: Unable to modify UI theming color

As I embark on creating my own theme in Storybook, I am closely following the guidelines outlined here: Currently, I have copied the necessary files from the website and everything seems to be working fine. However, I am facing an issue when trying to cus ...

After an error occurs, the Node.js Restify code will be executed

Within a Restify route, I have set up a router handler that calls a custom module for error checking. If the code encounters an error condition, it returns next(err) and displays the error message in the browser. However, the code does not stop executing a ...

Navigating through hidden input fields in Angular by utilizing the tab key

Seeking a method in Angular to navigate hidden inputs using tab functionality. I have several input forms that display only the text when not on focus. Is there a way to select an input and still be able to tab through the other hidden inputs? Any ideas o ...

How can we send state updates directly to a conditionally rendered React component?

I am currently developing a React application with a tab section that displays specific components upon clicking on a tab. Initially, I have my parent component: class Interface extends Component { constructor(props) { super(props); ...

Tips for sending information back to the previous screen in React Native Navigation version 5

Recently, I upgraded to react native navigation version 5 and now I am facing an issue with sending data back to the previous screen when making a goBack() call. To navigate to the next view, I use: const onSelectCountry = item => { console.log(it ...

In my specific scenario, what is the most effective method for retrieving data from an EntityFramework database using JavaScript?

Currently, within my ASP.NET MVC Core2 project, I have a model in the EF database that contains multiple properties: public class SchoolEvents { public long ID { get; set; } [Required] [StringLength(40, ErrorMessage = "Max 40 c ...

How to duplicate a single element from a list using the .clone() method in jQuery

My goal is to only add specific items from a list to a new list. For example, I want to add only the "banana" item to my second list. Currently, the code in my function adds all items from coll-selected-list to coll-grouped-list. How can I clone only a par ...

Troubleshooting the Issue of Table Append not Functioning in Live Environment

I'm currently in the process of developing a website using Bootstrap, and I'm facing an issue where one of the tables gets cleared out and updated with new data when a button is clicked. This functionality works perfectly fine during testing on V ...

Enhance the background property in createMuiTheme of Material-UI by incorporating additional properties using Typescript

I've been attempting to include a new property within createMuiTheme, but Typescript is not allowing me to do so. I followed the instructions provided here: https://next.material-ui.com/guides/typescript/#customization-of-theme I created a .ts file ...

How come I am receiving a null value for isMatch from bcrypt compare even though the two password strings match exactly?

Currently, I am attempting to authenticate a user based on a password. My approach involves using bcrypt compare to check if the user's requested password matches one stored in a MongoDB database. Despite the passwords being identical, I keep receivin ...

Require help extracting a JSON object

I am currently working with a JSON database to showcase ingredients on the webpage. For each recipe, I have a dedicated HTML page. To display the ingredients, I am hand typing them into an unordered list on the page. My challenge lies in trying to fetch t ...