Combining d3 and vue.js for enhanced interactive visualizations

I am currently in the process of integrating D3 with vue.js and I am following a straightforward guide available here:

The guide suggests appending a new div for each new bar, which I have successfully accomplished using a custom directive as shown in the attached code snippet.

My goal now is to leverage the capabilities of vue.js further by appending new components with props instead of just new div elements.

I am wondering how to achieve this - adding new components from a directive?


        var app = new Vue({
          el: '#app',
          data: {
            array: [4, 8, 15, 16, 23, 42]
          },
          directives: {
            chart: {
              bind(element, array) {
                d3.select(element)
                  .selectAll('div')
                  .data(array.value)
                  .enter()
                  .append('div')
                  .style('width', barValue => {
                    return barValue * 10 + 'px'
                  })
                  .text(barValue => {
                    return barValue
                  })
                }
              }
            }
          })
      

        .chart div {
          font: 10px sans-serif;
          background-color: steelblue;
          text-align: right;
          padding: 3px;
          margin: 1px;
          color: white;
        }
      

        <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
        <script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a0d6d5c5e0928e938e94">[email protected]</a>"></script>
        <div id="app">
           <div v-chart="array" class="chart">
          </div>
        </div>
      

Answer №1

Vue 2 emphasizes the use of directives for manipulating the DOM.

It's important to note that in Vue 2.0, components are the main method of reusing code and abstracting functionality. However, there are situations where direct access to the DOM on basic elements is necessary, making custom directives valuable.

Avoid incorporating components through a directive. If you are creating a chart using a directive, then your current approach is suitable.

Nevertheless, it is strongly recommended to implement this functionality within a component in Vue 2.

Using D3 in this scenario is excessive since all D3 does here is append some div elements, a task easily achieved with a component.

console.clear()

Vue.component("bar-chart", {
  props: ["chartData", "scale"],
  template: `
    <div>
      <div v-for="item in chartData" :style="{width: item * scale + 'px'}" class="chart">{{item}}</div>
    </div>
  `
})


new Vue({
  el: "#app",
  data: {
    array: [4, 8, 15, 16, 23, 42]
  },
})
.chart {
  font: 10px sans-serif;
  background-color: steelblue;
  text-align: right;
  padding: 3px;
  margin: 1px;
  color: white;
}
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6e181b0b2e5c405c4058">[email protected]</a>/dist/vue.js"></script>
<div id="app">
  <bar-chart :chart-data="array" scale="10"></bar-chart>
</div>

If you find yourself relying on D3, it's still advisable to handle it with a component rather than a directive.

console.clear()

Vue.component("bar-chart", {
  props:["chartData"],
  template:`<div class="chart"></div>`,
  mounted(){
    d3.select(this.$el)
          .selectAll('div')
          .data(this.chartData)
          .enter()
          .append('div')
          .style('width', barValue => {
            return barValue * 10 + 'px'
          })
          .text(barValue => {
            return barValue
          })
  }
})


new Vue({
  el:"#app",
  data: {
    array: [4, 8, 15, 16, 23, 42]
  },
})
.chart div {
  font: 10px sans-serif;
  background-color: steelblue;
  text-align: right;
  padding: 3px;
  margin: 1px;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2c5a59496c1e021e021a">[email protected]</a>/dist/vue.js"></script>
<div id="app">
  <bar-chart :chart-data="array"></bar-chart>
</div>

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

Modifying the DOM within a getJSON callback

My current challenge involves fetching data from the YouTube API and displaying it on my website. However, I am facing an issue where the DOM changes made inside the getJSON's callback function are not reflecting on the webpage. Even though I can see ...

How to manage rejections in async/await within the Array#map method

In my Node 8.1.2 project, I encountered a scenario where one file is calling another file's function within a map structure. While in a real example, I would normally use Promise.all on the map, that specific implementation is not the focus of this qu ...

Leverage environment variables in React JS to define distinct API URLs for production and development environments

For my React app, I started with create-react-app as the boilerplate. To make a request to my local server, I'm using fetch. fetch("http://localhost:3000/users") .then(function(res){ return res.json() }) .then(function(res){ return res.data }) ...

Switching between vertical and horizontal div layouts while reorganizing text fields within the top div

function toggleDivs() { var container = document.querySelector(".container"); var top = document.querySelector(".top"); var bottom = document.querySelector(".bottom"); if (container.style.flexDirection === "column") { container.style.flexDirec ...

Is it possible to efficiently transfer a Tensorflow.js Tensor between Node.js processes?

Currently, I am in the process of building an AI model using Tensorflow.js and Node.js. One of the challenges I am facing is handling a large dataset in a streaming manner due to its size being too massive to be stored in memory all at once. This task invo ...

The integration of query, URL, and body parameters is not working as expected in Seneca when using Seneca

I'm facing some difficulties with Seneca and seneca-web as a beginner. This is the current state of my code: "use strict"; var express = require('express'); var Web = require("seneca-web"); var bodyParser = require('body-parser' ...

What is the best way to access and display the innerText of elements that have been removed using console

When I call the updateCartTotal() function, my goal is to display in the console the items that have been removed from the shopping cart. Every time I click on the remove button, I want it to show the item and the price. However, instead of displaying the ...

Guide to iterating through a queue of promises (sequentially handling asynchronous messages)

Currently, I am working on processing a queue of promises (which are representations of messages) in a specific order and using AngularJS for the task. Just to give you an idea, let's say that I have a method called connect() which returns a promise ...

In PHP, it is essential to always complete the necessary information in form validation

I've been working on implementing JavaScript form validation, but I seem to be having trouble with testing for empty fields in the form. Whenever I submit a fully filled out form, it keeps asking me to fill in the blank fields. Here is the code I hav ...

When resizing an anchor tag with a percentage in CSS, the child image width may not scale accordingly

In short, I have multiple draggable images on a map enclosed in anchor tags (<a><img></a>) to enable keyboard dragging. The original image sizes vary, but they are all too large, so I reduced them to 20% of their original sizes using the ...

the conditional operator used without assigning the result to a variable

Exploring conditional operators on html canvas, I am seeking a streamlined approach to dynamically change stroke color based on conditions. Online examples have not provided a satisfactory solution in a single line of code. Currently, without using a cond ...

Breaking down and analyzing XML information

I have data that I need to retrieve from an XML file, split the result, parse it, and display it in an HTML element. Here is a snippet of the XML file: <Root> <Foo> <Bar> <BarType>Green</BarType> &l ...

The table disappears when there is no data available in the database

One of my challenges involves a table that displays data retrieved from a database. The code for this is as follows: <table class="table table-hover table-bordered" style="width:300px" id="contact"> <tbody data-bind="foreach:items"> ...

The console correctly detects the value, but is unable to set the innerHTML property of null

I am currently working on a webpage that allows users to sign in and create an account. The issue I'm facing is that when I try to display the user's information, I encounter the error 'Cannot set property 'innerHTML' of null.&apos ...

Determine if the input text field contains any text and store it in a variable using jQuery

I'm working on a form that includes radiobuttons and textfields. To keep track of the number of checked radiobuttons, I use this code: var $answeredRadiobuttons = $questions.find("input:radio:checked").length; But how do I store the number of textf ...

After mapping the elements of the array twice, generate a new array

Two differently formatted bits of data may be received, each requiring different character stripping methods. The variable names are temporary and will be changed once the function is operational. const cut = flatten.map(obj => { return obj.file. ...

Determine the specific cell involved in an HTML5 drag-and-drop interaction within a table

I've been experimenting with the HTML5 drag and drop functionality in an Angular project. Here's the setup I'm working with: A container containing draggable 'objects' A table where users can drop the dragged elements Following ...

Is there a way to incorporate locales in calculations involving percentages?

Given the number 4030.146852312 I want to retrieve the four decimal places from this number, resulting in: 4030.1468 Furthermore, I need to format this number according to the specified locale. For example: 4.030,1468 What is the best way to achieve thi ...

Retrieve data from Firestore using React and log it outside of the asynchronous function

Seeking a way to retrieve data from userRef and use it to initiate another asynchronous call to another document (e.g. bikes) in order to display that bikes doc on the page Currently, the userDetailslog in the Home screen function prints {"_U": ...

Utilizing various layouts in ASP.NET MVC with AngularJS

I am setting up two different layouts, one for visitors and one for management. Routes: app.config(['$routeProvider', function ( $routeProvider) { $routeProvider .when('/', { templateUrl: 'Home ...