Back to Blog

D3.js Tutorial: Create Custom Charts in Your Dashboard - Step by Step

January 31, 2025
xlanalysis Team

D3.js Tutorial: Create Custom Charts in Your Dashboard - Step by Step


Learn how to create custom D3.js visualizations in xlanalysis dashboards. This comprehensive tutorial walks you through building your first custom chart from scratch, with code examples and best practices.




Introduction


Creating custom visualizations with D3.js in xlanalysis opens up endless possibilities for your dashboards. Whether you need a unique chart type, a branded visualization, or an interactive experience that standard charts can't provide, D3.js gives you the power to build exactly what you need.


This tutorial will guide you through creating your first custom D3.js chart, from setup to completion. By the end, you'll understand how to:


  • Set up a D3.js visual in xlanalysis
  • Link it to your data
  • Write D3.js code to create a custom chart
  • Use the live preview feature
  • Debug and refine your visualization



Prerequisites


Before we start, make sure you have:


  • An xlanalysis account - Sign up if you haven't already
  • Data uploaded - At least one Excel/CSV file uploaded to your project
  • Basic understanding of JavaScript - You don't need to be an expert, but familiarity with variables, functions, and objects helps
  • A dashboard - Create a new dashboard or use an existing one



Step 1: Create a New D3.js Visual


1.1 Navigate to Your Dashboard


  1. Go to your Dashboards page
  2. Create a new dashboard or open an existing one
  3. Click the "+ Add Visual" button

1.2 Select Custom D3


  1. In the visual library, find and select "Custom D3"
  2. The visual configuration modal will open
  3. Notice the split layout: code editor on the left, live preview on the right



Step 2: Link Your Data


Before writing code, you need to connect your visual to data. You have three options:


Option A: Use a Table


  1. Select "Select Table" as your data source
  2. Choose a table from the dropdown
  3. Optionally select specific columns (or leave blank to use all columns)

Option B: Use a Saved Query


  1. Select "Use Saved Query" as your data source
  2. Choose a saved query from the dropdown
  3. The query preview will show below

Option C: Write Custom SQL


  1. Select "Write SQL Query" as your data source
  2. Write your SQL query in the editor
  3. Example: SELECT category, SUM(sales) as total_sales FROM Sales GROUP BY category

For this tutorial, we'll use a simple table with sales data.




Step 3: Understanding the Code Environment


When you write D3.js code in xlanalysis, you have access to these variables:


  • svg - The SVG container element (already created for you)
  • data - Your query results as a JavaScript array of objects
  • d3 - The full D3.js library
  • width - The width of your visual in pixels
  • height - The height of your visual in pixels

Data Format


Your data comes as an array of objects, where each object represents a row:


[
  { category: "Electronics", sales: 15000 },
  { category: "Clothing", sales: 8500 },
  { category: "Food", sales: 12000 }
]



Step 4: Build Your First Chart - A Simple Bar Chart


Let's create a simple bar chart step by step.


4.1 Set Up Margins and Dimensions


First, define margins and calculate the chart area:


// Define margins
const margin = { top: 20, right: 20, bottom: 40, left: 40 };

// Calculate chart dimensions
const chartWidth = width - margin.left - margin.right;
const chartHeight = height - margin.top - margin.bottom;

4.2 Create a Group Element


Create a group element and translate it to account for margins:


// Create a group element for the chart
const g = svg.append("g")
  .attr("transform", `translate(${margin.left},${margin.top})`);

4.3 Get Your Data Keys


Identify which columns to use for X and Y axes:


// Get the first column for X-axis (categories)
const xKey = data.length > 0 ? Object.keys(data[0])[0] : null;

// Get the second column for Y-axis (values)
const yKey = data.length > 0 ? Object.keys(data[0])[1] : null;

4.4 Create Scales


D3.js uses scales to map data values to pixel positions:


// X scale (for categories)
const xScale = d3.scaleBand()
  .domain(data.map(d => String(d[xKey])))
  .range([0, chartWidth])
  .padding(0.1); // Space between bars

// Y scale (for values)
const yScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => Number(d[yKey]) || 0)])
  .range([chartHeight, 0]); // Inverted because SVG Y-axis goes down

4.5 Draw the Bars


Create rectangles for each data point:


// Draw bars
g.selectAll(".bar")
  .data(data)
  .enter()
  .append("rect")
  .attr("class", "bar")
  .attr("x", d => xScale(String(d[xKey])))
  .attr("y", d => yScale(Number(d[yKey]) || 0))
  .attr("width", xScale.bandwidth())
  .attr("height", d => chartHeight - yScale(Number(d[yKey]) || 0))
  .attr("fill", "#22d3ee"); // Color

4.6 Add Axes


Add X and Y axes to make the chart readable:


// X axis
g.append("g")
  .attr("transform", `translate(0,${chartHeight})`)
  .call(d3.axisBottom(xScale));

// Y axis
g.append("g")
  .call(d3.axisLeft(yScale));

4.7 Complete Code


Here's the complete code for a simple bar chart:


// Set up margins and dimensions
const margin = { top: 20, right: 20, bottom: 40, left: 40 };
const chartWidth = width - margin.left - margin.right;
const chartHeight = height - margin.top - margin.bottom;

// Create chart group
const g = svg.append("g")
  .attr("transform", `translate(${margin.left},${margin.top})`);

// Get data keys
const xKey = data.length > 0 ? Object.keys(data[0])[0] : null;
const yKey = data.length > 0 ? Object.keys(data[0])[1] : null;

if (xKey && yKey) {
  // Create scales
  const xScale = d3.scaleBand()
    .domain(data.map(d => String(d[xKey])))
    .range([0, chartWidth])
    .padding(0.1);

  const yScale = d3.scaleLinear()
    .domain([0, d3.max(data, d => Number(d[yKey]) || 0)])
    .range([chartHeight, 0]);

  // Draw bars
  g.selectAll(".bar")
    .data(data)
    .enter()
    .append("rect")
    .attr("class", "bar")
    .attr("x", d => xScale(String(d[xKey])))
    .attr("y", d => yScale(Number(d[yKey]) || 0))
    .attr("width", xScale.bandwidth())
    .attr("height", d => chartHeight - yScale(Number(d[yKey]) || 0))
    .attr("fill", "#22d3ee");

  // Add axes
  g.append("g")
    .attr("transform", `translate(0,${chartHeight})`)
    .call(d3.axisBottom(xScale));

  g.append("g")
    .call(d3.axisLeft(yScale));
}



Step 5: Use Live Preview


As you write your code, the live preview panel on the right updates automatically:


  1. Type your code in the editor
  2. Watch the preview update in real-time
  3. See errors immediately if something goes wrong
  4. Iterate quickly - Make changes and see results instantly

The preview uses your actual data, so you'll see exactly how your chart will look.




Step 6: Save Your Visual


Once you're happy with your chart:


  1. Click "Save Visual" - This executes the query and adds the visual to your dashboard
  2. Or click "Save as Draft" - Save your code without executing the query (useful for work in progress)



Step 7: Advanced Example - Line Chart with Multiple Series


Let's create a more advanced example: a line chart with multiple series.


7.1 Prepare Your Data


For this example, assume your data has multiple value columns:


[
  { month: "Jan", sales: 1000, profit: 200 },
  { month: "Feb", sales: 1500, profit: 300 },
  { month: "Mar", sales: 1200, profit: 250 }
]

7.2 Complete Line Chart Code


// Set up
const margin = { top: 20, right: 30, bottom: 40, left: 50 };
const chartWidth = width - margin.left - margin.right;
const chartHeight = height - margin.top - margin.bottom;

const g = svg.append("g")
  .attr("transform", `translate(${margin.left},${margin.top})`);

// Get keys
const xKey = Object.keys(data[0])[0];
const valueKeys = Object.keys(data[0]).slice(1); // All columns except first

// Create scales
const xScale = d3.scalePoint()
  .domain(data.map(d => String(d[xKey])))
  .range([0, chartWidth]);

const maxValue = d3.max(data, d => 
  d3.max(valueKeys, key => Number(d[key]) || 0)
);

const yScale = d3.scaleLinear()
  .domain([0, maxValue])
  .range([chartHeight, 0]);

// Create line generator
const line = d3.line()
  .x(d => xScale(String(d[xKey])))
  .y(d => yScale(Number(d[valueKeys[0]]) || 0))
  .curve(d3.curveMonotoneX);

// Create color scale
const colorScale = d3.scaleOrdinal()
  .domain(valueKeys)
  .range(["#22d3ee", "#06b6d4", "#0891b2"]);

// Draw lines for each series
valueKeys.forEach((key, i) => {
  const lineGenerator = d3.line()
    .x(d => xScale(String(d[xKey])))
    .y(d => yScale(Number(d[key]) || 0))
    .curve(d3.curveMonotoneX);

  g.append("path")
    .datum(data)
    .attr("fill", "none")
    .attr("stroke", colorScale(key))
    .attr("stroke-width", 2)
    .attr("d", lineGenerator);
});

// Add axes
g.append("g")
  .attr("transform", `translate(0,${chartHeight})`)
  .call(d3.axisBottom(xScale));

g.append("g")
  .call(d3.axisLeft(yScale));



Step 8: Debugging Tips


8.1 Use Console Logging


Add console.log() statements to understand your data:


console.log("Data:", data);
console.log("First row:", data[0]);
console.log("Columns:", Object.keys(data[0]));
console.log("Data length:", data.length);

8.2 Check for Empty Data


Always check if data exists before using it:


if (data && data.length > 0) {
  // Your chart code here
} else {
  console.log("No data available");
}

8.3 Handle Missing Values


Data might have missing or null values:


const value = Number(d[yKey]) || 0; // Default to 0 if missing

8.4 Check the Preview


The live preview shows errors immediately. Read error messages carefully - they'll tell you what went wrong.




Step 9: Best Practices


9.1 Start Simple


Begin with a basic chart and add complexity gradually:


  1. First, just render the data
  2. Then add scales and axes
  3. Finally, add styling and interactivity

9.2 Use Meaningful Variable Names


// Good
const salesData = data;
const maxSales = d3.max(salesData, d => d.sales);

// Bad
const d = data;
const m = d3.max(d, x => x.s);

9.3 Add Comments


Comment your code, especially complex parts:


// Create a band scale for categories
// This evenly distributes categories across the width
const xScale = d3.scaleBand()
  .domain(data.map(d => d.category))
  .range([0, chartWidth]);

9.4 Test with Different Data


Your chart should work with different datasets. Test with:

  • Small datasets (1-5 rows)
  • Large datasets (100+ rows)
  • Missing values
  • Different column names



Step 10: Common Patterns


10.1 Color Scales


Use D3.js color scales for consistent coloring:


// Ordinal scale for categories
const colorScale = d3.scaleOrdinal()
  .domain(data.map(d => d.category))
  .range(d3.schemeCategory10);

// Sequential scale for values
const valueColorScale = d3.scaleSequential(d3.interpolateViridis)
  .domain([0, d3.max(data, d => d.value)]);

10.2 Tooltips


Add tooltips for interactivity (using D3.js selections):


g.selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("cx", d => xScale(d.x))
  .attr("cy", d => yScale(d.y))
  .attr("r", 5)
  .on("mouseover", function(event, d) {
    // Show tooltip
    d3.select(this).attr("r", 8);
  })
  .on("mouseout", function() {
    // Hide tooltip
    d3.select(this).attr("r", 5);
  });

10.3 Transitions


Add smooth animations:


g.selectAll("rect")
  .data(data)
  .transition()
  .duration(1000)
  .attr("height", d => chartHeight - yScale(d.value));



Resources for Learning D3.js


Official Resources


Learning Path


  1. Start with examples - Copy code from d3js.org and adapt it
  2. Understand scales - Scales are fundamental to D3.js
  3. Learn selections - How D3.js manipulates the DOM
  4. Practice with data - Try different data structures
  5. Add interactivity - Make your charts interactive



Troubleshooting


Chart Not Showing


  • Check your data - Use console.log(data) to verify data exists
  • Check scales - Make sure domain and range are set correctly
  • Check dimensions - Verify width and height are positive numbers

Bars/Lines in Wrong Position


  • Check scale ranges - Make sure ranges match your chart dimensions
  • Check data types - Convert strings to numbers with Number()
  • Check axis orientation - Remember SVG Y-axis goes down

Colors Not Working


  • Check color scale domain - Make sure it matches your data
  • Use valid colors - Hex codes, named colors, or CSS variables



Next Steps


Now that you've created your first custom D3.js chart:


  1. Experiment - Try different chart types from d3js.org
  2. Customize - Add your brand colors and styling
  3. Add interactivity - Make charts respond to user actions
  4. Share - Show off your custom visualizations



Conclusion


Creating custom D3.js visualizations in xlanalysis gives you complete control over how your data is presented. With the live preview feature, you can iterate quickly and see results instantly.


Remember:

  • Start simple and build complexity gradually
  • Use the live preview to see results as you code
  • Save as draft to preserve your work
  • Reference d3js.org for examples and inspiration

Your dashboards are now only limited by your imagination. Happy coding!




Ready to create your first custom chart? Open your dashboard and start building!


Ready to Build Your Own Dashboards?

Start creating professional dashboards from your Excel files today.

D3.js Tutorial: Create Custom Charts in Your Dashboard - Step by Step | xlanalysis Blog | xlanalysis