javascriptjqueryapexcharts

Update in Apexcharts the tickamount dynamically based on screen width


I'm testing for the first time some libraries to create graphs in JavaScript of Open Source type to understand which one is the most interesting and suitable for me.


I was trying to update tickamount in Apexcharts on xaxis with type: 'category' (with a simple JavaScript function code).

In the labels there are timestamps formatted as string.

I can't use the type: 'datetime' because some points in dates are null (there's not the example case, full filled).

So watch this snippet.

If I resize my browser window the tickAmount it's replaced with tickAmount: newtickamount correctly, but I got completely different values on the xaxis.

Open the full-size snippet to see the result on xaxis change (by clicking on the top right of the snippet).

It's a bug or I'm doing something wrong?

    var options = {
        chart: {
            width: '100%',
            height: '400px',
            stacked: false,
            toolbar: { show: false, },
        },
        labels: [
        "29 08 2024 07:04:31", "29 08 2024 07:04:41", "29 08 2024 07:04:51", "29 08 2024 07:05:01", "29 08 2024 07:05:11", "29 08 2024 07:05:21", "29 08 2024 07:05:31", "29 08 2024 07:05:41", "29 08 2024 07:05:51", "29 08 2024 07:06:01", "29 08 2024 07:06:11", "29 08 2024 07:06:21", "29 08 2024 07:06:31", "29 08 2024 07:06:41", "29 08 2024 07:06:51", "29 08 2024 07:07:01", "29 08 2024 07:07:11", "29 08 2024 07:07:21", "29 08 2024 07:07:31", "29 08 2024 07:07:41", "29 08 2024 07:07:51", "29 08 2024 07:08:01", "29 08 2024 07:08:11", "29 08 2024 07:08:21", "29 08 2024 07:08:31", "29 08 2024 07:08:41", "29 08 2024 07:08:51", "29 08 2024 07:09:01", "29 08 2024 07:09:11", "29 08 2024 07:09:21", "29 08 2024 07:09:31", "29 08 2024 07:09:41", "29 08 2024 07:09:51", "29 08 2024 07:10:01", "29 08 2024 07:10:11", "29 08 2024 07:10:21", "29 08 2024 07:10:31", "29 08 2024 07:10:41", "29 08 2024 07:10:51", "29 08 2024 07:11:01", "29 08 2024 07:11:11", "29 08 2024 07:11:21", "29 08 2024 07:11:31", "29 08 2024 07:11:41", "29 08 2024 07:11:51", "29 08 2024 07:12:01", "29 08 2024 07:12:11", "29 08 2024 07:12:21", "29 08 2024 07:12:31", "29 08 2024 07:12:41", "29 08 2024 07:12:51", "29 08 2024 07:13:01", "29 08 2024 07:13:11", "29 08 2024 07:13:21", "29 08 2024 07:13:31", "29 08 2024 07:13:41", "29 08 2024 07:13:51", "29 08 2024 07:14:01", "29 08 2024 07:14:11", "29 08 2024 07:14:21", "29 08 2024 07:14:31", "29 08 2024 07:14:41", "29 08 2024 07:14:51", "29 08 2024 07:15:01", "29 08 2024 07:15:11", "29 08 2024 07:15:21", "29 08 2024 07:15:31", "29 08 2024 07:15:41", "29 08 2024 07:15:51", "29 08 2024 07:16:01", "29 08 2024 07:16:11", "29 08 2024 07:16:21", "29 08 2024 07:16:31", "29 08 2024 07:16:41", "29 08 2024 07:16:51", "29 08 2024 07:17:01", "29 08 2024 07:17:11", "29 08 2024 07:17:21", "29 08 2024 07:17:31", "29 08 2024 07:17:41", "29 08 2024 07:17:51", "29 08 2024 07:18:01", "29 08 2024 07:18:11", "29 08 2024 07:18:21", "29 08 2024 07:18:31", "29 08 2024 07:18:41", "29 08 2024 07:18:51", "29 08 2024 07:19:01", "29 08 2024 07:19:11", "29 08 2024 07:19:21", "29 08 2024 07:19:31", "29 08 2024 07:19:41", "29 08 2024 07:19:51", "29 08 2024 07:20:01", "29 08 2024 07:20:11", "29 08 2024 07:20:21", "29 08 2024 07:20:31", "29 08 2024 07:20:41", "29 08 2024 07:20:51",
    ],

        series: [{
            name: 'Hello',
            info: 'hello',
            type: 'line',
            data: [
                357, 171, 472, 909, 707, 411, 470, 990, 112, 369, 428, 451, 44, 869, 710, 782, 718, 491, 479, 976, 438, 953, 976, 363, 886, 479, 274, 809, 625, 808, 569, 226, 158, 646, 196, 506, 754, 114, 513, 535, 271, 428, 155, 97, 412, 661, 181, 118, 616, 297, 23, 460, 344, 274, 467, 937, 839, 355, 290, 765, 647, 462, 90, 439, 737, 439, 194, 186, 973, 667, 181, 425, 84, 453, 43, 835, 99, 209, 580, 465, 329, 740, 541, 237, 17, 631, 916, 300, 745, 826, 63, 900, 990, 450, 560, 99, 21, 981, 954,
            ],

            },
        ],

        stroke: {
            width: 2,
            curve: 'smooth',
        },
        
        xaxis: {
            type: 'category',     //category    datetime     numeric
            //tickAmount: 20,
            tooltip: { enabled: false, },
            tickPlacement: 'on',
            labels: { rotate: -60, },
        },
        
        
        yaxis: [
          {
            show: true,
            labels: {
                show: true,
            },
            axisBorder: { show: false, },
            axisTicks: { show: false, },
            tooltip: { enabled: true, offsetX: -20, },
          },
        ],
        tooltip: {
            enabled: true,
            shared: true,
            intersect: false,
            inverseOrder: false,
            //custom: function({series, seriesIndex, dataPointIndex, w}) {   return 'HELLO!';  }),
        }       
    };

    var chart = new ApexCharts(document.querySelector("#chart"), options);
    chart.render();
      
      
      
      
      
      
      
  
    //Replacing tickamount
    function replace_tickamount(){
        width = document.body.clientWidth;
        newtickamount = 0;
        
        if (width > 1000){
            newtickamount = 10;
        } else if (width > 500) {
            newtickamount = 8;
        } else {
            newtickamount = 4;
        }
        
        chart.updateOptions({
            xaxis: { type: 'category', tickAmount: newtickamount, },
        });

    }



    addEventListener("resize", (event) => { 
      replace_tickamount();
    });

    
<div id="chart"></div>
<style>
@import url(https://fonts.googleapis.com/css?family=Roboto);
body { font-family: Roboto, sans-serif; }
#chart { max-width: 100%; border: 1px solid #000; }
</style>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>


EDIT AFTER THE ANSWER OF @kikon

Seems the "bug" it's bigger than I expected.

If you use the first solution you propose and you change the tickAmount manually, like

    newtickamount = 0;
    if (width > 1000){ newtickamount = 7; }
    chart.updateOptions({
        xaxis: { type: 'category', tickAmount: newtickamount, categories: options.labels, },
    });

you got some values of tickAmount differents.

Try to change and see.

For newtickamount = 5 the graph prints 6 ticks.

For newtickamount = 7 the graph prints 9 ticks.

For newtickamount = 10 the graph prints 11 ticks.

There's something wrong with the inner calculation (that also I didn't even ask for).

Graphically I would like to get a first and last value to make the result more beautiful visually (using a small function that uses chart.w.globals.categoryLabels.length).

But in these conditions it seems useless to change the tickamount.


Solution

  • You may say it's a bug; or a dubious sort of feature ...

    Apexcharts performs in certain conditions (horizontal bar + unsupported zoom + tick placement !== 'between', etc.) a conversion of x axis from category to numeric, see the source code. You can check that by adding a console.log(chart.w.config.xaxis.type) after chart.render() - you'll get numeric, not category, which you set. I suppose the reason for that is some intended optimization.

    To still preserve the original categories, it also creates an xaxis.labels.formatter option, that maps the new numbers to those original labels. However, when you updateOptions for the xaxis, that formatter is lost.

    The simplest solution seems to me to just set the categories option of the axis when you updateOptions:

    chart.updateOptions({
        xaxis: { type: 'category', tickAmount: newtickamount, categories: options.labels}
    })
    

    the original snippet with this change:

    var options = {
        chart: {
            width: '100%',
            height: '400px',
            stacked: false,
            toolbar: { show: false, },
        },
        labels: [
            "29 08 2024 07:04:31", "29 08 2024 07:04:41", "29 08 2024 07:04:51", "29 08 2024 07:05:01", "29 08 2024 07:05:11", "29 08 2024 07:05:21", "29 08 2024 07:05:31", "29 08 2024 07:05:41", "29 08 2024 07:05:51", "29 08 2024 07:06:01", "29 08 2024 07:06:11", "29 08 2024 07:06:21", "29 08 2024 07:06:31", "29 08 2024 07:06:41", "29 08 2024 07:06:51", "29 08 2024 07:07:01", "29 08 2024 07:07:11", "29 08 2024 07:07:21", "29 08 2024 07:07:31", "29 08 2024 07:07:41", "29 08 2024 07:07:51", "29 08 2024 07:08:01", "29 08 2024 07:08:11", "29 08 2024 07:08:21", "29 08 2024 07:08:31", "29 08 2024 07:08:41", "29 08 2024 07:08:51", "29 08 2024 07:09:01", "29 08 2024 07:09:11", "29 08 2024 07:09:21", "29 08 2024 07:09:31", "29 08 2024 07:09:41", "29 08 2024 07:09:51", "29 08 2024 07:10:01", "29 08 2024 07:10:11", "29 08 2024 07:10:21", "29 08 2024 07:10:31", "29 08 2024 07:10:41", "29 08 2024 07:10:51", "29 08 2024 07:11:01", "29 08 2024 07:11:11", "29 08 2024 07:11:21", "29 08 2024 07:11:31", "29 08 2024 07:11:41", "29 08 2024 07:11:51", "29 08 2024 07:12:01", "29 08 2024 07:12:11", "29 08 2024 07:12:21", "29 08 2024 07:12:31", "29 08 2024 07:12:41", "29 08 2024 07:12:51", "29 08 2024 07:13:01", "29 08 2024 07:13:11", "29 08 2024 07:13:21", "29 08 2024 07:13:31", "29 08 2024 07:13:41", "29 08 2024 07:13:51", "29 08 2024 07:14:01", "29 08 2024 07:14:11", "29 08 2024 07:14:21", "29 08 2024 07:14:31", "29 08 2024 07:14:41", "29 08 2024 07:14:51", "29 08 2024 07:15:01", "29 08 2024 07:15:11", "29 08 2024 07:15:21", "29 08 2024 07:15:31", "29 08 2024 07:15:41", "29 08 2024 07:15:51", "29 08 2024 07:16:01", "29 08 2024 07:16:11", "29 08 2024 07:16:21", "29 08 2024 07:16:31", "29 08 2024 07:16:41", "29 08 2024 07:16:51", "29 08 2024 07:17:01", "29 08 2024 07:17:11", "29 08 2024 07:17:21", "29 08 2024 07:17:31", "29 08 2024 07:17:41", "29 08 2024 07:17:51", "29 08 2024 07:18:01", "29 08 2024 07:18:11", "29 08 2024 07:18:21", "29 08 2024 07:18:31", "29 08 2024 07:18:41", "29 08 2024 07:18:51", "29 08 2024 07:19:01", "29 08 2024 07:19:11", "29 08 2024 07:19:21", "29 08 2024 07:19:31", "29 08 2024 07:19:41", "29 08 2024 07:19:51", "29 08 2024 07:20:01", "29 08 2024 07:20:11", "29 08 2024 07:20:21", "29 08 2024 07:20:31", "29 08 2024 07:20:41", "29 08 2024 07:20:51",
        ],
    
        series: [{
            name: 'Hello',
            info: 'hello',
            type: 'line',
            data: [
                357, 171, 472, 909, 707, 411, 470, 990, 112, 369, 428, 451, 44, 869, 710, 782, 718, 491, 479, 976, 438, 953, 976, 363, 886, 479, 274, 809, 625, 808, 569, 226, 158, 646, 196, 506, 754, 114, 513, 535, 271, 428, 155, 97, 412, 661, 181, 118, 616, 297, 23, 460, 344, 274, 467, 937, 839, 355, 290, 765, 647, 462, 90, 439, 737, 439, 194, 186, 973, 667, 181, 425, 84, 453, 43, 835, 99, 209, 580, 465, 329, 740, 541, 237, 17, 631, 916, 300, 745, 826, 63, 900, 990, 450, 560, 99, 21, 981, 954,
            ],
        }],
    
        stroke: {
            width: 2,
            curve: 'smooth',
        },
    
        xaxis: {
            type: 'category',     //category    datetime     numeric
            //tickAmount: 20,
            tooltip: { enabled: false, },
            tickPlacement: 'on',
            labels: { rotate: -60, },
        },
    
    
        yaxis: [
            {
                show: true,
                labels: {
                    show: true,
                },
                axisBorder: { show: false, },
                axisTicks: { show: false, },
                tooltip: { enabled: true, offsetX: -20, },
            },
        ],
        tooltip: {
            enabled: true,
            shared: true,
            intersect: false,
            inverseOrder: false,
            //custom: function({series, seriesIndex, dataPointIndex, w}) {   return 'HELLO!';  }),
        }
    };
    
    var chart = new ApexCharts(document.querySelector("#chart"), options);
    chart.render();
    console.log(chart.w.config.xaxis.type)
    
    //Replacing tickamount
    function replace_tickamount(){
        width = document.body.clientWidth;
        newtickamount = 0;
    
        if (width > 1000){
            newtickamount = 10;
        } else if (width > 500) {
            newtickamount = 8;
        } else {
            newtickamount = 4;
        }
    
        chart.updateOptions({
            xaxis: { type: 'category', tickAmount: newtickamount, categories: options.labels},
        });
    
    }
    
    addEventListener("resize", (event) => {
        replace_tickamount();
    });
    <div id="chart"></div>
    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>

    Another possibility is to explicitly preserve the labels.formatter that was set by the system when it converted the axis:

    chart.updateOptions({
        xaxis: { 
           tickAmount: newtickamount, 
           labels: {formatter: chart.w.config.xaxis.labels.formatter}
        }
    })
    

    the original snippet with this change:

    var options = {
        chart: {
            width: '100%',
            height: '400px',
            stacked: false,
            toolbar: { show: false, },
        },
        labels: [
            "29 08 2024 07:04:31", "29 08 2024 07:04:41", "29 08 2024 07:04:51", "29 08 2024 07:05:01", "29 08 2024 07:05:11", "29 08 2024 07:05:21", "29 08 2024 07:05:31", "29 08 2024 07:05:41", "29 08 2024 07:05:51", "29 08 2024 07:06:01", "29 08 2024 07:06:11", "29 08 2024 07:06:21", "29 08 2024 07:06:31", "29 08 2024 07:06:41", "29 08 2024 07:06:51", "29 08 2024 07:07:01", "29 08 2024 07:07:11", "29 08 2024 07:07:21", "29 08 2024 07:07:31", "29 08 2024 07:07:41", "29 08 2024 07:07:51", "29 08 2024 07:08:01", "29 08 2024 07:08:11", "29 08 2024 07:08:21", "29 08 2024 07:08:31", "29 08 2024 07:08:41", "29 08 2024 07:08:51", "29 08 2024 07:09:01", "29 08 2024 07:09:11", "29 08 2024 07:09:21", "29 08 2024 07:09:31", "29 08 2024 07:09:41", "29 08 2024 07:09:51", "29 08 2024 07:10:01", "29 08 2024 07:10:11", "29 08 2024 07:10:21", "29 08 2024 07:10:31", "29 08 2024 07:10:41", "29 08 2024 07:10:51", "29 08 2024 07:11:01", "29 08 2024 07:11:11", "29 08 2024 07:11:21", "29 08 2024 07:11:31", "29 08 2024 07:11:41", "29 08 2024 07:11:51", "29 08 2024 07:12:01", "29 08 2024 07:12:11", "29 08 2024 07:12:21", "29 08 2024 07:12:31", "29 08 2024 07:12:41", "29 08 2024 07:12:51", "29 08 2024 07:13:01", "29 08 2024 07:13:11", "29 08 2024 07:13:21", "29 08 2024 07:13:31", "29 08 2024 07:13:41", "29 08 2024 07:13:51", "29 08 2024 07:14:01", "29 08 2024 07:14:11", "29 08 2024 07:14:21", "29 08 2024 07:14:31", "29 08 2024 07:14:41", "29 08 2024 07:14:51", "29 08 2024 07:15:01", "29 08 2024 07:15:11", "29 08 2024 07:15:21", "29 08 2024 07:15:31", "29 08 2024 07:15:41", "29 08 2024 07:15:51", "29 08 2024 07:16:01", "29 08 2024 07:16:11", "29 08 2024 07:16:21", "29 08 2024 07:16:31", "29 08 2024 07:16:41", "29 08 2024 07:16:51", "29 08 2024 07:17:01", "29 08 2024 07:17:11", "29 08 2024 07:17:21", "29 08 2024 07:17:31", "29 08 2024 07:17:41", "29 08 2024 07:17:51", "29 08 2024 07:18:01", "29 08 2024 07:18:11", "29 08 2024 07:18:21", "29 08 2024 07:18:31", "29 08 2024 07:18:41", "29 08 2024 07:18:51", "29 08 2024 07:19:01", "29 08 2024 07:19:11", "29 08 2024 07:19:21", "29 08 2024 07:19:31", "29 08 2024 07:19:41", "29 08 2024 07:19:51", "29 08 2024 07:20:01", "29 08 2024 07:20:11", "29 08 2024 07:20:21", "29 08 2024 07:20:31", "29 08 2024 07:20:41", "29 08 2024 07:20:51",
        ],
    
        series: [{
            name: 'Hello',
            info: 'hello',
            type: 'line',
            data: [
                357, 171, 472, 909, 707, 411, 470, 990, 112, 369, 428, 451, 44, 869, 710, 782, 718, 491, 479, 976, 438, 953, 976, 363, 886, 479, 274, 809, 625, 808, 569, 226, 158, 646, 196, 506, 754, 114, 513, 535, 271, 428, 155, 97, 412, 661, 181, 118, 616, 297, 23, 460, 344, 274, 467, 937, 839, 355, 290, 765, 647, 462, 90, 439, 737, 439, 194, 186, 973, 667, 181, 425, 84, 453, 43, 835, 99, 209, 580, 465, 329, 740, 541, 237, 17, 631, 916, 300, 745, 826, 63, 900, 990, 450, 560, 99, 21, 981, 954,
            ],
        }],
    
        stroke: {
            width: 2,
            curve: 'smooth',
        },
    
        xaxis: {
            type: 'category',     //category    datetime     numeric
            //tickAmount: 20,
            tooltip: { enabled: false, },
            tickPlacement: 'on',
            labels: { rotate: -60, },
        },
    
    
        yaxis: [
            {
                show: true,
                labels: {
                    show: true,
                },
                axisBorder: { show: false, },
                axisTicks: { show: false, },
                tooltip: { enabled: true, offsetX: -20, },
            },
        ],
        tooltip: {
            enabled: true,
            shared: true,
            intersect: false,
            inverseOrder: false,
            //custom: function({series, seriesIndex, dataPointIndex, w}) {   return 'HELLO!';  }),
        }
    };
    
    var chart = new ApexCharts(document.querySelector("#chart"), options);
    chart.render();
    console.log(chart.w.config.xaxis.type)
    
    //Replacing tickamount
    function replace_tickamount(){
        width = document.body.clientWidth;
        newtickamount = 0;
    
        if (width > 1000){
            newtickamount = 10;
        } else if (width > 500) {
            newtickamount = 8;
        } else {
            newtickamount = 4;
        }
    
        chart.updateOptions({
          xaxis: {  
             tickAmount: newtickamount,
             labels: {
                formatter: chart.w.config.xaxis.labels.formatter
             }
          },
        });
    
    }
    
    addEventListener("resize", (event) => {
        replace_tickamount();
    });
    <div id="chart"></div>
    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>