📊 Chart Integration #
Complete guide to integrating and customizing charts in Admindek using ApexCharts.
Overview #
Admindek includes ApexCharts 4.7.0 as the primary charting library, providing 30+ chart types with responsive design and interactive features.
Basic Chart Setup #
1. HTML Container #
<!-- Chart container with unique ID -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">Sales Analytics</h5>
</div>
<div class="card-body">
<div id="sales-chart"></div>
</div>
</div>2. JavaScript Configuration (Actual Admindek Implementation) #
// Bar chart example from actual codebase (src/assets/js/widgets/bar-chart.js)
'use strict';
document.addEventListener('DOMContentLoaded', function () {
setTimeout(function () {
var options = {
series: [
{
name: 'News',
data: [53, 13, 30, 4]
}
],
chart: {
height: 250,
type: 'bar',
toolbar: {
show: false
}
},
colors: ['#1de9b6', '#a389d4', '#04a9f5', '#f44236'],
fill: {
type: 'gradient',
opacity: 1,
gradient: {
shade: 'dark',
type: 'vertical',
gradientToColors: ['#1dc4e9', '#899ed4', '#049df5', '#f48f36'],
stops: [0, 100]
}
},
plotOptions: {
bar: {
columnWidth: '35%',
distributed: true
}
},
dataLabels: {
enabled: false
},
legend: {
show: false
},
grid: {
show: false
},
yaxis: {
show: false
},
xaxis: {
axisBorder: {
show: false
},
categories: ['Sport', 'Music', 'Travel', 'News']
},
tooltip: {
fixed: {
enabled: false
},
x: {
show: false
},
y: {
title: {
formatter: function (seriesName) {
return '';
}
}
},
marker: {
show: false
}
}
};
var chart = new ApexCharts(document.querySelector('#bar-chart'), options);
chart.render();
}, 500);
});Chart Types #
Area Chart #
const areaOptions = {
chart: {
height: 300,
type: 'area',
toolbar: { show: false }
},
series: [{
name: 'Revenue',
data: [31, 40, 28, 51, 42, 109, 100]
}, {
name: 'Profit',
data: [11, 32, 45, 32, 34, 52, 41]
}],
colors: ['#4f46e5', '#10b981'],
fill: {
type: 'gradient',
gradient: {
shadeIntensity: 1,
opacityFrom: 0.7,
opacityTo: 0.3
}
},
stroke: {
curve: 'smooth'
},
xaxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul']
}
};Bar Chart #
const barOptions = {
chart: {
height: 350,
type: 'bar'
},
series: [{
name: 'Products Sold',
data: [44, 55, 57, 56, 61, 58, 63, 60, 66]
}],
colors: ['#4f46e5'],
plotOptions: {
bar: {
borderRadius: 4,
horizontal: false,
}
},
dataLabels: {
enabled: false
},
xaxis: {
categories: ['Q1', 'Q2', 'Q3', 'Q4', 'Q5', 'Q6', 'Q7', 'Q8', 'Q9']
}
};Donut Chart #
const donutOptions = {
chart: {
type: 'donut',
height: 300
},
series: [44, 55, 41, 17, 15],
labels: ['Desktop', 'Mobile', 'Tablet', 'Smart TV', 'Others'],
colors: ['#4f46e5', '#10b981', '#f59e0b', '#ef4444', '#6c757d'],
plotOptions: {
pie: {
donut: {
size: '70%',
labels: {
show: true,
total: {
show: true,
label: 'Total',
color: '#6c757d',
formatter: function (w) {
return w.globals.seriesTotals.reduce((a, b) => {
return a + b;
}, 0);
}
}
}
}
}
}
};Dashboard Integration #
Widget Chart Pattern #
// Reusable widget chart function
function createWidgetChart(selector, options = {}) {
const defaultOptions = {
chart: {
height: 60,
type: 'area',
sparkline: {
enabled: true
}
},
stroke: {
curve: 'smooth',
width: 2
},
fill: {
type: 'gradient',
gradient: {
shadeIntensity: 1,
opacityFrom: 0.5,
opacityTo: 0.1
}
},
tooltip: {
fixed: {
enabled: false
},
x: {
show: false
},
marker: {
show: false
}
}
};
const finalOptions = { ...defaultOptions, ...options };
const chart = new ApexCharts(document.querySelector(selector), finalOptions);
chart.render();
return chart;
}
// Usage in KPI widgets
createWidgetChart('#revenue-spark', {
series: [{
data: [25, 66, 41, 89, 63, 25, 44, 12, 36, 9, 54]
}],
colors: ['#4f46e5']
});Real-time Chart Updates #
// Real-time data updates
let realtimeChart;
function initRealtimeChart() {
const options = {
chart: {
height: 350,
type: 'line',
animations: {
enabled: true,
easing: 'linear',
dynamicAnimation: {
speed: 1000
}
},
toolbar: { show: false }
},
series: [{
name: 'Live Data',
data: []
}],
colors: ['#4f46e5'],
stroke: {
curve: 'smooth',
width: 3
},
xaxis: {
type: 'datetime',
range: 300000 // 5 minutes
},
yaxis: {
max: 100
}
};
realtimeChart = new ApexCharts(document.querySelector("#realtime-chart"), options);
realtimeChart.render();
// Start updating data
setInterval(updateRealtimeChart, 2000);
}
function updateRealtimeChart() {
const newData = {
x: new Date().getTime(),
y: Math.floor(Math.random() * 100)
};
realtimeChart.appendData([{
data: [newData]
}]);
}Advanced Customization #
Custom Themes #
// Dark theme configuration
const darkThemeOptions = {
theme: {
mode: 'dark',
palette: 'palette1'
},
chart: {
background: '#1e293b',
foreColor: '#e2e8f0'
},
grid: {
borderColor: '#334155'
},
xaxis: {
axisBorder: {
color: '#334155'
},
axisTicks: {
color: '#334155'
}
},
yaxis: {
axisBorder: {
color: '#334155'
}
}
};
// Apply theme based on current mode
function getChartTheme() {
const isDark = document.body.getAttribute('data-pc-theme') === 'dark';
return isDark ? darkThemeOptions : {};
}
// Use in chart creation
const chartOptions = {
// ... other options
...getChartTheme()
};Responsive Configuration #
const responsiveOptions = {
chart: {
height: 350
},
responsive: [{
breakpoint: 768,
options: {
chart: {
height: 250
},
plotOptions: {
bar: {
horizontal: true
}
},
legend: {
position: 'bottom'
}
}
}, {
breakpoint: 480,
options: {
chart: {
height: 200
},
legend: {
show: false
}
}
}]
};Data Integration #
API Data Loading #
// Fetch data from API
async function loadChartData(endpoint) {
try {
const response = await fetch(endpoint);
const data = await response.json();
return data;
} catch (error) {
console.error('Error loading chart data:', error);
return null;
}
}
// Create chart with API data
async function createAPIChart() {
const data = await loadChartData('/api/sales-data');
if (data) {
const options = {
chart: {
type: 'line',
height: 350
},
series: data.series,
xaxis: {
categories: data.categories
},
colors: ['#4f46e5']
};
const chart = new ApexCharts(document.querySelector("#api-chart"), options);
chart.render();
}
}CSV Data Import #
// Parse CSV data for charts
function parseCSVForChart(csvText) {
const lines = csvText.split('\n');
const headers = lines[0].split(',');
const categories = [];
const series = [];
// Initialize series for each column (except first)
for (let i = 1; i < headers.length; i++) {
series.push({
name: headers[i].trim(),
data: []
});
}
// Parse data rows
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(',');
if (values.length > 1) {
categories.push(values[0].trim());
for (let j = 1; j < values.length; j++) {
const value = parseFloat(values[j]) || 0;
series[j - 1].data.push(value);
}
}
}
return { categories, series };
}
// Use with file input
document.getElementById('csv-input').addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const csvData = parseCSVForChart(e.target.result);
const options = {
chart: {
type: 'line',
height: 350
},
series: csvData.series,
xaxis: {
categories: csvData.categories
}
};
const chart = new ApexCharts(document.querySelector("#csv-chart"), options);
chart.render();
};
reader.readAsText(file);
}
});Chart Interactions #
Click Events #
const interactiveOptions = {
// ... chart options
chart: {
events: {
dataPointSelection: function(event, chartContext, config) {
const selectedData = {
seriesIndex: config.seriesIndex,
dataPointIndex: config.dataPointIndex,
value: config.w.config.series[config.seriesIndex].data[config.dataPointIndex]
};
console.log('Selected:', selectedData);
// Update other charts or UI based on selection
updateRelatedCharts(selectedData);
}
}
}
};Zoom and Pan #
const zoomOptions = {
chart: {
type: 'line',
zoom: {
enabled: true,
type: 'x'
},
pan: {
enabled: true,
type: 'x'
}
},
// ... other options
};Performance Optimization #
Lazy Loading Charts #
// Lazy load charts when they come into view
const chartObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const chartId = entry.target.getAttribute('data-chart-id');
loadChart(chartId, entry.target);
chartObserver.unobserve(entry.target);
}
});
});
// Observe chart containers
document.querySelectorAll('[data-chart-id]').forEach(container => {
chartObserver.observe(container);
});
function loadChart(chartId, container) {
// Load chart configuration based on ID
const options = getChartOptions(chartId);
const chart = new ApexCharts(container, options);
chart.render();
}Memory Management #
// Clean up charts when navigating away
let chartInstances = [];
function createChart(selector, options) {
const chart = new ApexCharts(document.querySelector(selector), options);
chart.render();
// Track instance for cleanup
chartInstances.push(chart);
return chart;
}
// Clean up on page unload
window.addEventListener('beforeunload', () => {
chartInstances.forEach(chart => {
if (chart && chart.destroy) {
chart.destroy();
}
});
chartInstances = [];
});Troubleshooting #
Common Issues #
Chart not rendering:
// Ensure container exists before creating chart
const container = document.querySelector("#chart-container");
if (container) {
const chart = new ApexCharts(container, options);
chart.render();
} else {
console.error('Chart container not found');
}Responsive issues:
// Force resize after container size changes
window.addEventListener('resize', () => {
if (chart) {
chart.resize();
}
});Data formatting:
// Ensure data is properly formatted
function validateChartData(data) {
if (!Array.isArray(data)) {
console.error('Chart data must be an array');
return false;
}
return data.every(item =>
typeof item === 'number' ||
(typeof item === 'object' && item.x && item.y)
);
}Summary #
ApexCharts integration in Admindek provides:
- 30+ chart types for all visualization needs
- Responsive design that adapts to all screen sizes
- Real-time updates for dynamic data
- Interactive features with click, zoom, and pan
- Theme integration with Admindek's design system
- Performance optimization with lazy loading
- API integration for dynamic data sources
This comprehensive charting system enables you to create professional data visualizations that seamlessly integrate with Admindek's design and functionality.