0
votes

I want to resize multiple Highcharts on my page and am able to do so on button click.

One of my charts (last one) has a dropdown associated with it. When I change the value in the dropdown to update the last chart, and then click on the button reflow, I get Uncaught TypeError: Cannot read property 'reflow' of undefined error.

I am able to resize(reflow)the charts if I make no updates to the charts via the dropdown. But once I click on the value in the dropdown, The reflow breaks and gives me an error.

My code:

HTML:

<div id="container" style="width: 400px; height: 300px; margin: 1em; border: 1px solid gray"></div>
<div id="container2" style="width: 400px; height: 300px; margin: 1em; border: 1px solid gray"></div>
<div id="drop" style="width: 400px; height: 300px; margin: 1em; border: 1px solid gray"></div>
<select id="mydropdown" multiple></select>
<button id="set-div-size" class="autocompare">REFLOW!</button>

My JavaScript

const obj = {
        '10-10-2020': [{
            cat: 'cat',
            abc: 1,
            xyz: 5,
            pqr: 6,
            jkl: 1,
            mno: 9
        },
        {
            cat: 'dog',
            abc: 3,
            xyz: 4,
            pqr: 1,
            jkl: 6,
            mno: 1
        },
        {
            cat: 'rat',
            abc: 7,
            xyz: 2,
            pqr: 9,
            jkl: 3,
            mno: 0
        },
        ],
        '10-07-2020': [{
            cat: 'cat',
            abc: 1,
            xyz: 5,
            pqr: 6,
            jkl: 1,
            mno: 9
        },
        {
            cat: 'dog',
            abc: 3,
            xyz: 4,
            pqr: 1,
            jkl: 6,
            mno: 1
        },
        {
            cat: 'rat',
            abc: 7,
            xyz: 2,
            pqr: 9,
            jkl: 3,
            mno: 0
        },
        ],
        '10-09-2020': [{
            cat: 'cat',
            abc: 1,
            xyz: 5,
            pqr: 6,
            jkl: 1,
            mno: 9
        },
        {
            cat: 'dog',
            abc: 3,
            xyz: 4,
            pqr: 1,
            jkl: 6,
            mno: 1
        },
        {
            cat: 'rat',
            abc: 7,
            xyz: 2,
            pqr: 9,
            jkl: 3,
            mno: 0
        },
        ],
    };

    const colors = ['#000', 'red', 'blue'];
    let arr = ['abc', 'xyz', 'pqr', 'jkl', 'mno'];

    const data = (sd) => Object.entries(obj).map(([k, g]) => {
        var cos = {
            ['name']: k,
            ['data']: g.map(entry => entry[sd]),
            ['stack']: sd,
            ['color']: colors[i++ % colors.length],
        }

        return cos;
    });


    let i = 0;
    let x = data('abc');


    let chartOptions = {
        chart: {
            type: 'column'
        },

        xAxis: {
            categories: ['One', 'Two', 'Three', 'Four', 'Five']
        },

        plotOptions: {
            column: {
                stacking: 'normal'
            }
        },

        series: x
    }

    arr.forEach(c => {
        $(`#mydropdown`).append(`<option value='${c}'>${c}</option>`);
    });
    $(`select#mydropdown option[value='abc']`).prop('selected', 'selected');


    let drop = new Highcharts.chart('drop', chartOptions);

    let opts;
    $(`#mydropdown`).on('change', function() {
        chartOptions.series = [],
        opts = [];
        $('option:selected', this).each(function() {
            i = 0;
            chartOptions.series = [...chartOptions.series, ...data($(this).val())];
            opts.push(this.value);
        });
        let drop = new Highcharts.chart('drop', chartOptions);
        console.log(Highcharts.charts); 
    });

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var chart = Highcharts.chart('container', {

    xAxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    },

    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
    }]

});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var chart2 = Highcharts.chart('container2', {

    xAxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    },

    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
    }]

});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
let charts_arr =['chart', 'chart2', 'drop']
var wide = false;
$('#set-div-size').click(function () {
    $('#container').width(wide ? 400 : 500);
    $('#container2').width(wide ? 400 : 500);
    $('#drop').width(wide ? 400 : 500);
    wide = !wide;
    Highcharts.charts.forEach(d=>{
        d.reflow();
        console.log(Highcharts.charts); 
    });
});

I have a working fiddle: my_fiddle

My error when I try to resize after updating the last chart from dropdown:

Error

1

1 Answers

1
votes

The error you get in the console is enough clear. Indeed, in this foreach:

Highcharts.charts.forEach(d => {
    d.reflow();

you may have undefined values for d variable. Said that you need to skip all those values:

Highcharts.charts.forEach(d => {
     if (d != undefined)
         d.reflow();

const obj = {
        '10-10-2020': [{
            cat: 'cat',
            abc: 1,
            xyz: 5,
            pqr: 6,
            jkl: 1,
            mno: 9
        },
            {
                cat: 'dog',
                abc: 3,
                xyz: 4,
                pqr: 1,
                jkl: 6,
                mno: 1
            },
            {
                cat: 'rat',
                abc: 7,
                xyz: 2,
                pqr: 9,
                jkl: 3,
                mno: 0
            },
        ],
        '10-07-2020': [{
            cat: 'cat',
            abc: 1,
            xyz: 5,
            pqr: 6,
            jkl: 1,
            mno: 9
        },
            {
                cat: 'dog',
                abc: 3,
                xyz: 4,
                pqr: 1,
                jkl: 6,
                mno: 1
            },
            {
                cat: 'rat',
                abc: 7,
                xyz: 2,
                pqr: 9,
                jkl: 3,
                mno: 0
            },
        ],
        '10-09-2020': [{
            cat: 'cat',
            abc: 1,
            xyz: 5,
            pqr: 6,
            jkl: 1,
            mno: 9
        },
            {
                cat: 'dog',
                abc: 3,
                xyz: 4,
                pqr: 1,
                jkl: 6,
                mno: 1
            },
            {
                cat: 'rat',
                abc: 7,
                xyz: 2,
                pqr: 9,
                jkl: 3,
                mno: 0
            },
        ],
    };

    const colors = ['#000', 'red', 'blue'];
    let arr = ['abc', 'xyz', 'pqr', 'jkl', 'mno'];

    const data = (sd) => Object.entries(obj).map(([k, g]) => {
        var cos = {
                ['name']: k,
            ['data']: g.map(entry => entry[sd]),
    ['stack']: sd,
            ['color']: colors[i++ % colors.length],
}

return cos;
});


let i = 0;
let x = data('abc');


let chartOptions = {
    chart: {
        type: 'column'
    },

    xAxis: {
        categories: ['One', 'Two', 'Three', 'Four', 'Five']
    },

    plotOptions: {
        column: {
            stacking: 'normal'
        }
    },

    series: x
}

arr.forEach(c => {
    $(`#mydropdown`).append(`<option value='${c}'>${c}</option>`);
});
$(`select#mydropdown option[value='abc']`).prop('selected', 'selected');


let drop = new Highcharts.chart('drop', chartOptions);

let opts;
$(`#mydropdown`).on('change', function() {
    chartOptions.series = [],
            opts = [];
    $('option:selected', this).each(function() {
        i = 0;
        chartOptions.series = [...chartOptions.series, ...data($(this).val())];
        opts.push(this.value);
    });
    let drop = new Highcharts.chart('drop', chartOptions);
    console.log(Highcharts.charts);
});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var chart = Highcharts.chart('container', {

    xAxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
            'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
        ]
    },

    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
    }]

});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var chart2 = Highcharts.chart('container2', {

    xAxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
            'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
        ]
    },

    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
    }]

});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
let charts_arr = ['chart', 'chart2', 'drop']
var wide = false;
$('#set-div-size').click(function() {
    $('#container').width(wide ? 400 : 500);
    $('#container2').width(wide ? 400 : 500);
    $('#drop').width(wide ? 400 : 500);
    wide = !wide;
    Highcharts.charts.forEach(d => {
        if (d != undefined)
            d.reflow();
    console.log(Highcharts.charts);
});
});
#container {
    min-width: 310px;
    max-width: 800px;
    height: 400px;
    margin: 0 auto
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>


<div id="container" style="width: 400px; height: 300px; margin: 1em; border: 1px solid gray"></div>
<div id="container2" style="width: 400px; height: 300px; margin: 1em; border: 1px solid gray"></div>
<div id="drop" style="width: 400px; height: 300px; margin: 1em; border: 1px solid gray"></div>
<select id="mydropdown" multiple></select>
<button id="set-div-size" class="autocompare">REFLOW</button>