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

"Enhance Your Phonegap Android App with Pinch Zoom Capability

I am currently working on an Android Application with the help of jQuery Mobile and Phonegap. My goal is to implement pinch zoom functionality on the App pages. I have come across several suggestions that involve using the following line, but unfortunatel ...

JavaScript code to remove everything in a string after the last occurrence of a certain

I have been working on a JavaScript function to cut strings into 140 characters, ensuring that words are not broken in the process. Now, I also want the text to make more sense by checking for certain characters (like ., ,, :, ;) and if the string is bet ...

"Learn the process of transferring data from one controller to another in your application

After adding categoryCtrl and ProductCtrl, the code line: console.log(category); is functioning correctly. I am looking for a way to bind this data to the product controller using a for loop or any other method. .controller('CategoryCtrl', funct ...

Need to swiftly modify values of css attributes?

Here is a snippet of the code I am working with: <div></div> <button> Go </button> div { width: 50px; height: 50px; border: 1px solid #ccc; } var bgs = ['red', 'blue', 'yellow', 'green&apo ...

Differences between MobX local state and global state

I am currently working on a React project using mobx to manage the application state. For dump components that interact with external data sources (such as ajax calls, filtering or mapping arrays), I simply manipulate the data in those components. Howeve ...

How can I make v-for display additional profiles to achieve an infinite scroll effect?

Hey there! I've got a Firestore database set up to fetch profiles and display them on a page using v-for. I want to implement infinite scroll for a smoother user experience. Here's the JavaScript composable code I'm working with: import { pr ...

Having trouble connecting DB and D3 using PHP. Struggling to follow D3noob's tutorial to completion

First and foremost, I want to express my gratitude to the amazing community here for all that I have learned. However, I'm currently facing some difficulties in finding the solution I need. I've encountered issues while trying to follow the inst ...

Tips for modifying prop values after they have been initially set in a Component

When working with a Vue component, it is important to remember that setting the 'props' immediately requires updating the collection to include additional properties. The component code is as follows: Vue.component('blog-post', { pr ...

Utilizing SVG within Sproutcore allows for seamless access to DOM nodes and the ability to effortlessly bind Sproutcore events directly to the DOM

Exploring Sproutcore, I am delving into the world of SVG (Standard Vector Graphics) integration within the app. The goal is to utilize a canvas for drawing elements like lines, boxes, and images, all of which SVG offers. My approach involved incorporating ...

Is comparing strings in JavaScript as efficient as comparing numbers?

Considering creating a JavaScript enum library involves deciding how to store the values, I'm at a crossroads. Should I opt for speed in comparison or prioritize readability during debugging by using strings or numbers? While objects are an option too ...

The default value in an Ionic select dropdown remains hidden until it is clicked for the first time

Having an issue with my ion-select in Ionic version 6. I have successfully pre-selected a value when the page loads, but it doesn't show up in the UI until after clicking the select (as shown in pic 2). I'm loading the data in the ionViewWillEnt ...

Monaco Editor: Module 'monaco-editor' is missing despite being successfully installed

During the development of my desktop application with electron, I encountered an issue with installing Monaco Editor. After using npm install monaco-editor, running the application resulted in a message saying Cannot find module 'monaco-editor'. ...

Creating captchas seems like a mistake in reasoning to me

I am encountering an issue with my code. I created a basic newbie-level captcha using Javascript. Below is the code snippet: <!DOCTYPE html> <html> <head> <style> </style> </head> <body> <h1>T ...

JavaScript callbacks are not executed synchronously

My Objective : I am attempting to initiate a payment order in the payment gateway server and then send back the order details to the client using Firebase cloud functions. This process involves utilizing firebase cloud functions. The Order() function ha ...

Is it necessary to use callbacks when using mongoose's findbyid with express to retrieve an object from the database? Are callbacks still important in modern JavaScript frameworks?

I'm currently exploring the express local library tutorial on MDN docs and wanted to try out returning an object without relying on a callback method. When I provide the request object parameter for the id to the findById mongoose method like this va ...

Creating dynamic ng-model for input type [text] in AngularJS

Here is the current situation I'm dealing with in my code: <form name="task_form" ng-app="myApp" ng-submit="tasksubmit()"> <ul class="items-list"> <li ng-repeat="task in taskslist ...

How to Execute Another JavaScript Script Using IF/ELSE Statement?

I am trying to dynamically call one of two JavaScript files based on a condition. Here is the code I have: <script type="text/javascript"> if(b_condition) <script type="text/javascript" src="http://script1.js"></script> else <scri ...

How can you create a personalized sorting order using odata?

Within my AngularApp, I retrieve data from a WebAPI using OData queries. All the retrieved results contain both a date and an integer status code. The status codes range from 1 to 4. I am aiming to organize my results in such a way that all items with a ...

Router Express, parsing the body, and submitting a POST request

I have been experimenting with express.Router to organize my routes and testing post requests using Postman. I noticed that when I make a post request to /test without using router body-parser, everything works fine and I can view the body content. However ...

Tips for Utilizing Environmental Variables within a Vue Application's index.html File

My website has an index file with all the necessary meta tags, stylesheets, and scripts: <!DOCTYPE html> <html lang="en"> <head> <!-- Required Meta --> <meta charset="UTF-8"> <meta http-equi ...