Skip to content

Chart.js Project — Interactive Sales Dashboard

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Chart.js Project. We cover key concepts, practical examples, and best practices to help you master this topic.

This project walks through building a full-featured sales dashboard with Chart.js combining bar, line, doughnut, and radar charts with filtering and real-time data updates.

What You'll Learn

By the end of this project, you will architect a multi-chart dashboard layout, connect charts to shared data sources, implement date range filtering, add real-time data push, deploy with Responsive Design, and ensure Accessibility.

Dashboard Structure

var Dashboard = {
    data: null,
    filters: { startDate: null, endDate: null, region: 'all' },
    charts: {},

    init: function() {
        this.loadData();
        this.createCharts();
        this.setupFilters();
    },

    loadData: function() {
        fetch('/api/sales-data')
            .then(function(res) { return res.json(); })
            .then(function(data) {
                Dashboard.data = data;
                Dashboard.renderAll();
            });
    },

    renderAll: function() {
        var filtered = this.getFilteredData();
        Object.keys(this.charts).forEach(function(key) {
            Dashboard.charts[key].data = filtered;
            Dashboard.charts[key].update();
        });
    }
};

Filter Handler

function setupFilters() {
    d3.select('#date-range').on('change', function() {
        Dashboard.filters.startDate = this.value.split(',')[0];
        Dashboard.filters.endDate = this.value.split(',')[1];
        Dashboard.renderAll();
    });

    d3.select('#region-select').on('change', function() {
        Dashboard.filters.region = this.value;
        Dashboard.renderAll();
    });
}

Common Mistakes

1. Chart Instances Not Saved

Each chart must be saved to a variable for updates. Creating charts without references makes them impossible to update.

2. Data Transformation per Chart

Transform data once in a central place. Each chart should not re-parse or re-filter independently.

3. Not Destroying Charts on Page Leave

Leaving a page with active charts causes memory leaks. Call chart.destroy() in the page lifecycle.

4. Overcomplicating the Layout

Start with a simple grid. Add charts incrementally. Test each chart before adding the next.

5. Ignoring Error States

API calls can fail. Show error messages and retry buttons instead of blank spaces.

Practice Questions

Q1: How do you organize multiple charts in one page? A: Use a chart manager object that holds references to all chart instances and provides a central update function.

Q2: How do you share data between charts? A: Store data in a central state. Each chart reads from the state and updates when the state changes.

Q3: What is the best way to handle filter changes? A: Re-compute filtered data from the central state, then call chart.update('none') on each chart.

Q4: How do you ensure responsive layout? A: Use CSS Grid for layout, set responsive: true on each chart, and use container queries for breakpoints.

Q5: How do you add real-time updates? A: Use chartjs-plugin-streaming for the line chart and call chart.update('none') when new data arrives.

Challenge: Add export functionality: a button that downloads the entire dashboard as a PNG image using html2canvas.

FAQ

Should I use one large chart or multiple small charts?

Multiple focused charts are easier to read and maintain. One large chart becomes cluttered.

How do I deploy a Chart.js dashboard?

Build static files with your bundler. Deploy to Netlify, Vercel, or GitHub Pages.

Can I use Chart.js with React or Vue?

Yes. Use react-chartjs-2 or vue-chartjs wrapper libraries for framework integration.

How do I add authentication to the dashboard?

Token-based auth on the API side. Chart.js is client-side and does not handle auth.

How do I make the dashboard print-friendly?

Use @media print CSS rules. Set chart background to white and remove interactive elements.

Try It Yourself

Build a mini dashboard with bar, line, and doughnut charts.

<!DOCTYPE html>
<html>
<head>
    <title>Sales Dashboard</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        body { font-family: sans-serif; padding: 20px; background: #f5f5f5; }
        .dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; max-width: 900px; margin: 0 auto; }
        .card { background: white; border-radius: 8px; padding: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
        .card h3 { margin: 0 0 8px; font-size: 13px; color: #666; text-transform: uppercase; }
        .card.full { grid-column: 1 / -1; }
        canvas { width: 100% !important; height: auto !important; }
        #filters { margin-bottom: 12px; }
        #filters select { padding: 6px 10px; border-radius: 6px; border: 1px solid #ddd; }
    </style>
</head>
<body>
<div class="dashboard">
    <div class="card full"><h3>Dashboard</h3><div id="filters"><select id="year-select"><option value="2024">2024</option><option value="2025" selected>2025</option></select></div></div>
    <div class="card"><h3>Revenue</h3><canvas id="barChart"></canvas></div>
    <div class="card"><h3>Trend</h3><canvas id="lineChart"></canvas></div>
    <div class="card full"><h3>Distribution</h3><canvas id="doughnutChart" style="max-width:300px;margin:0 auto;"></canvas></div>
</div>
<script>
var revenueData = [30, 45, 40, 60, 55, 70, 65, 80, 75, 90, 85, 100];
var trendData = [20, 28, 35, 42, 40, 55, 50, 62, 58, 70, 68, 78];
var distData = [35, 25, 20, 15, 5];

var barChart = new Chart(document.getElementById('barChart'), { type: 'bar', data: { labels: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], datasets: [{ label: 'Revenue', data: revenueData, backgroundColor: '#4ecdc4' }] }, options: { responsive: true, maintainAspectRatio: true, plugins: { legend: { display: false } } } });

var lineChart = new Chart(document.getElementById('lineChart'), { type: 'line', data: { labels: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], datasets: [{ label: 'Trend', data: trendData, borderColor: '#ff6b35', fill: false, tension: 0.4 }] }, options: { responsive: true, maintainAspectRatio: true, plugins: { legend: { display: false } } } });

var doughnutChart = new Chart(document.getElementById('doughnutChart'), { type: 'doughnut', data: { labels: ['North America', 'Europe', 'Asia', 'South America', 'Africa'], datasets: [{ data: distData, backgroundColor: ['#ff6b35', '#4ecdc4', '#2a9d8f', '#e8a87c', '#95e1d3'] }] }, options: { responsive: true, maintainAspectRatio: true } });
</script>
</body>
</html>

What's Next

Explore Leaflet.js for interactive maps.

Getting Started — Interactive maps with Leaflet.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro