Chart (Chart.js)

Simple yet flexible JavaScript charting for designers & developers.

Chart.js documentation share-external-link-1

How to use

Import helper file to access all Dashly helper functions.

import * as helper from './helpers';

Define a cssPrefix variable to be able to use CSS variables within JavaScript

const cssPrefix = helper.getCSSVariable('--prefix');

Import chart vendor file which imports all the necessary files from Chart.js and contains the default settings.

import(/* webpackChunkName: 'chart.js' */ './vendors/chart')
.then(() => {
 // furter code
})
.catch(console.warn);

Bar chart

<div class="chart-container flex-grow-1 h-275px">
    <canvas id="salesChart"></canvas>
</div>
// dashly/theme/src/js/user.js
    
const salesChart = document.getElementById('salesChart');

if(salesChart) {
    import(/* webpackChunkName: 'chart.js' */ './vendors/chart')
    .then(() => {
        new Chart(salesChart, {
         // The type of chart we want to create
            type: 'bar',
        
         // The data for our dataset
            data: {
                labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
                datasets: [
                    {
                        label: 'Projections',
                        data: [12440, 15021, 10081, 10984, 8409, 12532, 13986, 19227, 12636, 10171, 6753, 15589],
                        backgroundColor: helper.getCSSVariable(`${cssPrefix}primary`)
                    },
                    {
                        label: 'Actual',
                        data: [12357, 13665, 9071, 9914, 5115, 12291, 10010, 19092, 11976, 9174, 5189, 14523],
                        backgroundColor: helper.getCSSVariable(`${cssPrefix}light`),
                        borderRadius: 30
                    }
                ]
            },
        
         // Configuration options
            options: {
                scales: {
                    x: {
                        stacked: true,
                        gridLines: {
                            display: false
                        }
                    },
                    y: {
                        stacked: true,
                        ticks: {
                            callback: (value, index, values) => {
                                return value > 0 ? '$' + Math.floor(value / 1000) + 'k' : value;
                            }
                        }
                    }
                },
                plugins: {
                    tooltip: {
                        callbacks: {
                            label: context => {
                                return new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}).format(context.parsed.y);
                            },
                            labelColor: context => {
                                return {
                                    backgroundColor: context.dataset.backgroundColor
                                };
                            }
                        }
                    }
                }
                
            }
        });
    })
    .catch(console.warn);
}

Line chart

<div class="chart-container h-150px">
    <canvas id="incomeChart"></canvas>
</div>
// dashly/theme/src/js/user.js
    
const incomeChart = document.getElementById('incomeChart');
       
if(incomeChart) {
    import(/* webpackChunkName: 'chart.js' */ './vendors/chart')
    .then(() => {
        new Chart(incomeChart, {
         // The type of chart we want to create
            type: 'line',

         // The data for our dataset
            data: {
                labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
                datasets: [
                    {
                        backgroundColor: (context) => {
                            const chart = context.chart;
                            const {ctx, chartArea} = chart;
                    
                            if (!chartArea) {
                                return null;
                            }
                            return helper.getGradient(
                                ctx,
                                chartArea,
                                `rgba(${helper.getCSSVariable(`${cssPrefix}primary-rgb`)}, 0.5)`,
                                `rgba(${helper.getCSSVariable(`${cssPrefix}primary-rgb`)}, 0.2)`,
                                `rgba(${helper.getCSSVariable(`${cssPrefix}primary-rgb`)}, 0)`
                            );
                        },
                        data: [400, 1000, 1000, 2500, 3000, 1500, 4000, 5000, 8000, 6000, 5500, 6500]
                    }
                ]
            },

         // Configuration options
            options: {
                layout: {
                    padding: {
                        top: 2,
                        bottom: -10
                    }
                },
                scales: {
                    x: {
                        ticks: {
                            display: false
                        },
                        grid: {
                            drawOnChartArea: true
                        }
                    },
                    y: {
                        display: false
                    }
                },
                plugins: {
                    tooltip: {
                        callbacks: {
                            label: function(context) {
                                return new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}).format(context.parsed.y);
                            }
                        }
                    }
                }
            }
        });
    })
    .catch(console.warn);
}

Doughnut chart (rounded)Exclusive

ordered products

329

<div class="chart-container flex-grow-1">
    <canvas id="orderStatusChart"></canvas>

    <!-- Labels -->
    <div class="position-absolute top-50 start-50 translate-middle text-center">
        <p class="fs-5 mb-0 text-muted lh-sm">ordered products</p>
        <h3 class="display-2 fw-bold mb-0">329</h3>
    </div>
</div>
// dashly/theme/src/js/user.js

const orderStatusChart = document.getElementById('orderStatusChart');
        
if(orderStatusChart){
    import(/* webpackChunkName: 'chart.js' */ './vendors/chart')
    .then(() => {
        new Chart(orderStatusChart, {
         // The type of chart we want to create
            type: 'roundedDoughnut',
        
         // The data for our dataset
            data: {
                labels: [
                    'Delivered',
                    'In progress',
                    'To-do'
                ],
                datasets: [
                    {
                        label: 'Order status',
                        data: [29, 45, 26],
                        backgroundColor: [
                            helper.getCSSVariable(`${cssPrefix}primary`),
                            helper.getCSSVariable(`${cssPrefix}dark`),
                            helper.getCSSVariable(`${cssPrefix}gray-300`)
                        ]
                    }
                ]
            },

         // Configuration options
            options: {
                plugins: {
                    tooltip: {  
                        callbacks: {
                            label: (context) => {
                                return context.parsed + '%';
                            }
                        }
                    }
                }
            }
        });
    })
    .catch(console.warn);
}

Line chart (toggle)

Use data-toggle="chart" attribute with data-target="#idOfTheChartElement" and data-dataset="indexOfTheDataset" attribute to switch between datasets. data-action="toggle" atrribute is optional, toggle is the default value.

<div class="d-flex justify-content-end mb-5">
    <!-- Label -->
    <h5 class="d-flex align-items-center text-uppercase link-secondary fw-semibold mb-0 cursor-pointer" data-toggle="chart" data-target="#salesReportChart" data-dataset="0">
        <span class="legend-circle-lg bg-primary"></span>
        Income
    </h5>

    <!-- Label -->
    <h5 class="d-flex align-items-center text-uppercase link-secondary fw-semibold mb-0 ms-4 cursor-pointer" data-toggle="chart" data-target="#salesReportChart" data-dataset="1">
        <span class="legend-circle-lg bg-dark"></span>
        Expense
    </h5>
</div>

<div class="chart-container flex-grow-1 h-275px">
    <canvas id="salesReportChart"></canvas>
</div>
// dashly/theme/src/js/user.js

const salesReportChart = document.getElementById('salesReportChart');

if(salesReportChart) {
    import(/* webpackChunkName: 'chart.js' */ './vendors/chart')
    .then(() => {
        new Chart(salesReportChart, {
         // The type of chart we want to create
            type: 'line',

         // The data for our dataset
            data: {
                labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
                datasets: [
                    {
                        label: 'Income',
                        data: [28, 70, 68, 77, 35, 24, 18, 73, 29, 43, 19, 24],
                        borderWidth: 4,
                        borderColor: helper.getCSSVariable(`${cssPrefix}primary`)
                    },
                    {
                        label: 'Expense',
                        data: [18, 23, 79, 37, 19, 45, 55, 72, 79, 57, 32, 59],
                        borderWidth: 4,
                        borderColor: helper.getCSSVariable(`${cssPrefix}dark`),
                        hidden: true
                    }
                ]
            },

         // Configuration options
            options: {
                scales: {
                    y: {
                        ticks: {
                            callback: (value, index, values) => {
                                return value > 0 ? '$' + value + 'k' : value;
                            }
                        }
                    }
                },
                plugins: {
                    tooltip: {
                        callbacks: {
                            label: (context) => {
                                return new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}).format(context.parsed.y);
                            }
                        }
                    }
                }
            }
        });
    })
    .catch(console.warn);
}

Show/hide datasets

Use data-toggle="chart" attribute with data-target="#idOfTheChartElement" and data-dataset="indexOfTheDataset" with data-action="visibility" atrribute to show/hide datasets in the chart.

<div class="d-flex justify-content-end mb-5">
    <ul class="nav">
        <li class="nav-item" data-toggle="chart" data-action="visibility" data-target="#overviewChart" data-dataset="0">
            <a class="nav-link chart-legend" href="#">
                <span class="legend-circle-lg bg-white border border-2 border-primary"></span>
                Expected revenue
            </a>
        </li>
        <li class="nav-item" data-toggle="chart" data-action="visibility" data-target="#overviewChart" data-dataset="1">
            <a class="nav-link chart-legend" href="#">
                <span class="legend-circle-lg rounded-0 h-4px bg-blue"></span>
                Actual revenue
            </a>
        </li>
    </ul>
</div>

<div class="chart-container h-250px">
    <canvas id="overviewChart"></canvas>
</div>
// dashly/theme/src/js/user.js

const overviewChart = document.getElementById('overviewChart');

if(overviewChart) {
    import(/* webpackChunkName: 'chart.js' */ './vendors/chart')
    .then(() => {
        new Chart(overviewChart, {
            // The type of chart we want to create
            type: 'line',
        
            // The data for our dataset
            data: {
                labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
                datasets: [
                    {
                        label: 'Expected',
                        data: [9440, 18021, 34081, 43804, 30409, 22532, 21986, 27227, 32636, 30171, 32753, 19589],
                        borderColor: helper.getCSSVariable(`${cssPrefix}primary`),
                        
                        pointRadius: 4,
                        pointBorderWidth: 3,
                        pointBorderColor: helper.getCSSVariable(`${cssPrefix}primary`),
                        pointBackgroundColor: helper.getCSSVariable(`${cssPrefix}white`),
                        
                        pointHoverRadius: 4,
                        pointHoverBorderWidth: 3,
                        pointHoverBorderColor: helper.getCSSVariable(`${cssPrefix}primary`),
                        pointHoverBackgroundColor: helper.getCSSVariable(`${cssPrefix}primary`),
                        tension: 0
                    },
                    {
                        label: 'Actual',
                        data: [2440, 9247, 23081, 30839, 39923, 36532, 28386, 34227, 38636, 37171, 25753, 25589],
                        borderWidth: 2,
                        borderDash: [5, 5],
                        borderColor: `rgba(${helper.getCSSVariable(`${cssPrefix}blue-rgb`)}, 0.75)`,
                        pointBackgroundColor: helper.getCSSVariable(`${cssPrefix}blue`),
                        tension: 0
                    }
                ]
            },
        
            // Configuration options
            options: {
                scales: {
                    x: {
                        gridLines: {
                            display: false
                        }
                    },
                    y: {
                        ticks: {
                            callback: (value, index, values) => {
                                return value > 0 ? '$' + ((value < 1000000) ? Math.floor(value / 1000) + 'k' : Math.floor(value / 1000000) + 'M') : value;
                            }
                        }
                    }
                },
                plugins: {
                    tooltip: {
                        mode: 'index',
                        callbacks: {
                            label: context => {
                                return new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}).format(context.parsed.y);
                            },
                            labelColor: context => {
                                return {
                                    backgroundColor: context.dataset.borderColor
                                }
                            }
                        }
                    },
                    mouseLine: {
                        enabled: true
                    }
                }
                
            }
        });
    })
    .catch(console.warn);
}
}