ApexCharts.js
Modern, Interactive Charts for Your Data Visualization Needs
ApexCharts is a modern JavaScript charting library that helps developers create beautiful, interactive visualizations for web pages. With a focus on smooth animations, responsive design, and advanced features, ApexCharts makes data visualization both powerful and accessible.
 In SmartAdmin, ApexCharts is integrated with a custom wrapper (apexchartsWrapper.js) that ensures visual consistency with the rest of the application and enhances the library with SmartAdmin-specific features. 
Installation
ApexCharts is included in the SmartAdmin theme with a custom wrapper. Here's how to set it up:
1. Basic Setup (Already Included)
// The following files are already included in the SmartAdmin theme:
// - apexcharts.esm.js (Original ApexCharts library)
// - apexchartsWrapper.js (SmartAdmin wrapper)2. Initialize a Chart
// Import the SmartAdmin ApexCharts wrapper
import SmartApexCharts from './pathTo/apexchart/apexchartsWrapper.js';
document.addEventListener('DOMContentLoaded', function() {
    // Create a basic bar chart
    const options = {
        chart: {
            type: 'bar',
            height: 350
        },
        series: [{
            name: 'Sales',
            data: [30, 40, 45, 50, 49, 60, 70, 91, 125]
        }],
        xaxis: {
            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep']
        }
    };
    
    const chart = new SmartApexCharts(
        document.querySelector('#my-chart'), 
        options
    );
    
    chart.render();
});HTML Structure
<!-- Basic Chart Container -->
<div id="my-chart"></div>
<!-- Panel-Based Chart Container (Recommended) -->
<div id="panel-1" class="panel">
    <div class="panel-hdr">
        <h2>Sales <span class="fw-300"><i>Overview</i></span></h2>
        <div class="panel-toolbar">
            <button class="btn btn-panel" data-action="panel-collapse">
                <!-- Panel controls -->
            </button>
        </div>
    </div>
    <div class="panel-container show">
        <div class="panel-content">
            <div id="my-chart"></div>
        </div>
    </div>
</div>- Always use the SmartApexChartsclass from the wrapper instead of the originalApexChartsto ensure proper integration with SmartAdmin.
- The wrapper automatically applies SmartAdmin styling and prevents CSS injection from the original library.
- For more advanced documentation, refer to the official ApexCharts documentation.
SmartAdmin Wrapper
SmartAdmin includes a custom wrapper for ApexCharts that enhances the library with theme-specific features. The wrapper is defined in apexchartsWrapper.js.
// Excerpt from the ApexCharts wrapper
class SmartApexCharts extends OriginalApexCharts {
    // Icon mapping for toolbar
    static iconMap = {
        'apexcharts-zoomin-icon': 'plus-circle',
        'apexcharts-zoomout-icon': 'minus-circle',
        'apexcharts-zoom-icon': 'plus',
        'apexcharts-pan-icon': 'move',
        'apexcharts-reset-icon': 'refresh-ccw',
        'apexcharts-menu-icon': 'menu'
    };
    constructor(el, options) {
        // Ensure options object exists
        options = options || {};
        options.chart = options.chart || {};
        
        // Global styling defaults
        const defaults = {
            chart: {
                fontFamily: 'inherit',
                disableCssInjection: true
            },
            title: {
                style: {
                    color: window.colorMap.bootstrapVars.bodyColor.hex
                }
            },
            // ... additional defaults
        };
        // Merge options with defaults
        options = SmartApexCharts.deepMerge(defaults, options);
        
        // Call parent constructor with merged options
        super(el, options);
        
        // Style observer and other enhancements
        // ...
    }
    
    // Replace toolbar icons with custom sprite system icons
    _replaceToolbarIcons(toolbar) {
        // ... icon replacement code
    }
}Chart Configuration
ApexCharts offers extensive configuration options. Here are some common chart types and configurations:
Bar Chart
const barOptions = {
    chart: {
        type: 'bar',
        height: 350
    },
    plotOptions: {
        bar: {
            horizontal: false,
            columnWidth: '55%',
            borderRadius: 4
        }
    },
    dataLabels: {
        enabled: false
    },
    stroke: {
        show: true,
        width: 2,
        colors: ['transparent']
    },
    series: [{
        name: 'Net Profit',
        data: [44, 55, 57, 56, 61, 58, 63]
    }, {
        name: 'Revenue',
        data: [76, 85, 101, 98, 87, 105, 91]
    }],
    xaxis: {
        categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    fill: {
        opacity: 1
    },
    tooltip: {
        y: {
            formatter: function (val) {
                return "$ " + val + " thousands"
            }
        }
    }
};
const barChart = new SmartApexCharts(
    document.querySelector('#bar-chart'), 
    barOptions
);
barChart.render();Line Chart
const lineOptions = {
    chart: {
        type: 'line',
        height: 350,
        zoom: {
            enabled: true
        }
    },
    series: [{
        name: "Desktops",
        data: [10, 41, 35, 51, 49, 62, 69, 91, 148]
    }],
    title: {
        text: 'Product Trends by Month',
        align: 'left'
    },
    grid: {
        row: {
            colors: ['#f3f3f3', 'transparent'],
            opacity: 0.5
        }
    },
    xaxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep']
    }
};
const lineChart = new SmartApexCharts(
    document.querySelector('#line-chart'), 
    lineOptions
);
lineChart.render();Area Chart
const areaOptions = {
    chart: {
        type: 'area',
        height: 350,
        stacked: true
    },
    dataLabels: {
        enabled: false
    },
    stroke: {
        curve: 'smooth'
    },
    series: [{
        name: 'South',
        data: [31, 40, 28, 51, 42, 109, 100]
    }, {
        name: 'North',
        data: [11, 32, 45, 32, 34, 52, 41]
    }],
    xaxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul']
    },
    tooltip: {
        x: {
            format: 'dd/MM/yy HH:mm'
        }
    },
    fill: {
        type: 'gradient',
        gradient: {
            shadeIntensity: 1,
            opacityFrom: 0.7,
            opacityTo: 0.9,
            stops: [0, 90, 100]
        }
    }
};
const areaChart = new SmartApexCharts(
    document.querySelector('#area-chart'), 
    areaOptions
);
areaChart.render();Pie Chart
const pieOptions = {
    chart: {
        type: 'pie',
        height: 350
    },
    series: [44, 55, 13, 43, 22],
    labels: ['Team A', 'Team B', 'Team C', 'Team D', 'Team E'],
    responsive: [{
        breakpoint: 480,
        options: {
            legend: {
                position: 'bottom'
            }
        }
    }]
};
const pieChart = new SmartApexCharts(
    document.querySelector('#pie-chart'), 
    pieOptions
);
pieChart.render();SmartAdmin Integration
For optimal integration with SmartAdmin, consider these tips:
Using Theme Colors
Use SmartAdmin color variables for consistent styling:
// Use SmartAdmin color variables
const options = {
    // ... other options
    colors: [
        'var(--primary-500)',
        'var(--success-500)',
        'var(--warning-500)',
        'var(--danger-500)',
        'var(--info-500)'
    ],
    fill: {
        colors: [
            'var(--primary-300)',
            'var(--success-300)',
            'var(--warning-300)',
            'var(--danger-300)',
            'var(--info-300)'
        ]
    }
};Responsive Configuration
Configure charts to be responsive based on screen size:
const options = {
    // ... other options
    chart: {
        height: 350,
        type: 'line',
        animations: {
            enabled: true,
            easing: 'easeinout',
            speed: 800
        },
        toolbar: {
            show: true
        },
        zoom: {
            enabled: true
        },
        responsive: [{
            breakpoint: 576,
            options: {
                chart: {
                    height: 250,
                    toolbar: {
                        show: false
                    }
                },
                legend: {
                    position: 'bottom',
                    offsetY: 0
                }
            }
        }]
    }
};Dark Mode Compatibility
Make your charts compatible with both light and dark themes:
// Check if dark mode is active
const isDarkMode = document.documentElement.classList.contains('theme-dark');
const options = {
    // ... other options
    chart: {
        foreColor: isDarkMode ? '#ffffff' : '#373a3c'
    },
    theme: {
        mode: isDarkMode ? 'dark' : 'light'
    },
    tooltip: {
        theme: isDarkMode ? 'dark' : 'light'
    }
};
// Listen for theme changes if needed
document.addEventListener('themeChanged', function(e) {
    const isDark = e.detail.isDark;
    chart.updateOptions({
        chart: {
            foreColor: isDark ? '#ffffff' : '#373a3c'
        },
        theme: {
            mode: isDark ? 'dark' : 'light'
        },
        tooltip: {
            theme: isDark ? 'dark' : 'light'
        }
    });
});Advanced Features
API Methods
// Get a reference to the chart
const chart = new SmartApexCharts(element, options);
chart.render();
// Update series data
chart.updateSeries([{
    name: 'Sales',
    data: [40, 55, 65, 11, 23, 44, 55, 75, 88]
}]);
// Update options
chart.updateOptions({
    title: {
        text: 'Updated Title'
    },
    colors: ['var(--danger-500)']
});
// Add data point
chart.appendData([{
    data: [20]
}]);
// Toggle series visibility
chart.toggleSeries('Series Name');
// Show/hide specific data point's tooltip
chart.toggleDataPointSelection(2, 0);
// Reset zoom
chart.resetSeries();
// Destroy the chart
chart.destroy();Dynamic Data Updates
// Create a chart with real-time data updates
const options = {
    chart: {
        type: 'line',
        height: 350,
        animations: {
            enabled: true,
            easing: 'linear',
            dynamicAnimation: {
                speed: 1000
            }
        },
        toolbar: {
            show: false
        },
        zoom: {
            enabled: false
        }
    },
    series: [{
        name: 'Server Load',
        data: [10, 15, 12, 14, 16, 18, 15, 17, 14, 13]
    }],
    stroke: {
        curve: 'smooth',
        width: 3
    },
    xaxis: {
        categories: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00']
    },
    markers: {
        size: 0
    }
};
const chart = new SmartApexCharts(
    document.querySelector('#real-time-chart'), 
    options
);
chart.render();
// Update data every 1 second
setInterval(function() {
    // Generate new data point
    const newValue = Math.floor(Math.random() * 10) + 10;
    
    // Get current time for x-axis label
    const now = new Date();
    const timeLabel = now.getHours() + ':' + (now.getMinutes() < 10 ? '0' : '') + now.getMinutes();
    
    // Update chart
    chart.updateSeries([{
        data: [...chart.w.globals.series[0].slice(1), newValue]
    }]);
    
    chart.updateOptions({
        xaxis: {
            categories: [...chart.w.globals.xaxis.categories.slice(1), timeLabel]
        }
    });
}, 1000);Mixed Chart Types
const mixedOptions = {
    chart: {
        height: 350,
        type: 'line'
    },
    series: [{
        name: 'Website',
        type: 'column',
        data: [440, 505, 414, 671, 227, 413, 201, 352, 752, 320, 257, 160]
    }, {
        name: 'Social Media',
        type: 'line',
        data: [23, 42, 35, 27, 43, 22, 17, 31, 22, 22, 12, 16]
    }],
    stroke: {
        width: [0, 4]
    },
    title: {
        text: 'Traffic Sources'
    },
    labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    xaxis: {
        type: 'category'
    },
    yaxis: [{
        title: {
            text: 'Website Visits'
        }
    }, {
        opposite: true,
        title: {
            text: 'Social Media'
        }
    }]
};
const mixedChart = new SmartApexCharts(
    document.querySelector('#mixed-chart'), 
    mixedOptions
);
mixedChart.render();Troubleshooting
- Chart not rendering? Ensure the container element exists in the DOM before initializing.
- Colors not applying? Make sure CSS variables are properly defined and accessible.
- Icons missing in toolbar? Verify the SmartApexCharts wrapper is being used instead of the original library.
- Custom styles not working? Check that you're not overriding the wrapper's style management.
Debugging Techniques
// Debug chart initialization
try {
    const chart = new SmartApexCharts(
        document.querySelector('#chart'), 
        options
    );
    chart.render();
} catch (error) {
    console.error('Chart initialization error:', error);
}
// Check if container exists
const container = document.querySelector('#chart');
if (!container) {
    console.error('Chart container not found');
    return;
}
// Verify series data
console.log('Chart series data:', options.series);
// Force explicit dimensions if auto-sizing issues
const options = {
    chart: {
        height: 350,
        width: '100%',
        background: '#f8f9fa', // Visible background to check rendering
    },
    // ...other options
};Common Error Fixes
// Fix for empty or null data
const validateData = (data) => {
    if (!data || !Array.isArray(data)) {
        return [0]; // Default fallback value
    }
    
    // Replace null/undefined values with 0
    return data.map(val => val === null || val === undefined ? 0 : val);
};
const options = {
    // ...other options
    series: [{
        name: 'Sales',
        data: validateData(salesData)
    }]
};
// Fix for charts in hidden elements (tabs, modals)
document.querySelector('.nav-tabs').addEventListener('shown.bs.tab', function (e) {
    // Redraw charts in newly visible tab
    const tabId = e.target.getAttribute('href');
    const charts = document.querySelectorAll(tabId + ' .apexchart');
    
    charts.forEach(chart => {
        if (chart.__smartChart) {
            chart.__smartChart.render();
        }
    });
});Further Resources
For more advanced usage and detailed API documentation, refer to these resources:
