Skip to content

Using dropdown filter to dynamic update Highchart

currently I was trying to add a dropdown filter button on my chart to let users select a specific values from a data attribute and filter the related data shown on the chart.

I populated my data’s attribute to the select unit, and I was trying to update the chart with parse the data from the selective value, but seems the data didn’t update on the HighChart.

Here is my code: jsfiddle

const data = [
{
    "Data": "aaa",
    "Media": "1",
    "Row": "1",
    "Column": "3",
    "Code": "24",
},
{
    "Data": "aaa",
    "Media": "2",
    "Row": "1",
    "Column": "1",
    "Code": "24",
},
{
    "Data": "aaa",
    "Media": "3",
    "Row": "1",
    "Column": "3",
    "Code": "24",
},
{
    "Data": "aaa",
    "Media": "4",
    "Row": "1",
    "Column": "2",
    "Code": "24",
},
{
    "Data": "aaa",
    "Media": "1",
    "Row": "2",
    "Column": "1",
    "Code": "24",
},

    // populate Media to dropdown list
$.each(data, function (index, record) {
    $('<option>', {
        value: record.Media,
        text: record.Media
    }).appendTo("#select_media");
});

// remove duplicate value from dropdown list
var optionValues =[];
$('#select_media option').each(function(){
if($.inArray(this.value, optionValues) >-1){
    $(this).remove()
}else{
    optionValues.push(this.value);
}
});

// getting drop down list value
var mediaselect = document.getElementById("select_media").value


mediaselect_str = String(mediaselect)

const parsedData = []
data.forEach(obj => {
    if (obj.Media == mediaselect_str) {
    parsedData.push({
        x: parseInt(obj.Row),
        y: parseInt(obj.Column),
        label: [obj.Data, obj.Media, obj.Code]
    })
    }
});

var chart = Highcharts.chart('tray_container', {
    chart: {
        type: 'heatmap',
        width: 500,
        height: 500,            
    
    },
    title: {
        text: null
    },
    plotOptions: {
        heatmap: {
            borderColor: "black",
            paddingRight: 100
        },
    },
    series: [{
        name: null,
        borderWidth: 1,
        data: parsedData,
        dataLabels: {
            inside: true,//Show 
            enabled: true,
            useHTML: true,
            opacity: 1,
            verticalAlign:'middle',
            align: 'center',
            style: {
                textShadow: 'none',
                HcTextStroke: null,
                display: 'block'
        },
            formatter: function() {
            const label = this.point.label;
            return `${label[1]} <br/> ${label[2]} <br/> ${label[0]}`
            }
        },
    }]
});

Is there anything I did wrong? Thank you.

=================================================================

Updated: Solution from JMS work prefectly, but in my real case my json data was called from somewhere so this will be a function. Based on JMS’s method the result was while I make selection from dropdown it counldn’t find update() function since it was nested inside my function. Sorry I’m still new in the javascript and I can’t figure out how to solve it.

function generate_chart(data) {
// populate Media to dropdown list
$.each(data, function (index, record) {
    $('<option>', {
        value: record.Media,
        text: record.Media
    }).appendTo("#select_media");
});

// remove duplicate value from dropdown list
var optionValues =[];
$('#select_media option').each(function(){
if($.inArray(this.value, optionValues) >-1){
    $(this).remove()
}else{
    optionValues.push(this.value);
}
});

update();
function update() {
// find the maximun of x & y values by row and column
var max_x = Math.max.apply(Math, fildata.map(function(mx) {
    return mx.OutputRow;
}))
var max_y = Math.max.apply(Math, fildata.map(function(my) {
    return my.OutputColumn;
}))
console.log(max_x, max_y)

// assign x & y axis array with the maxiumn 
var x = Array(max_x).fill().map((element, index) => index)
var y = Array(max_y).fill().map((element, index) => index)


// getting drop down list value
var mediaselect = document.getElementById("select_media").value


mediaselect_str = String(mediaselect)

const parsedData = []
data.forEach(obj => {
    if (obj.Media == mediaselect_str) {
    parsedData.push({
        x: parseInt(obj.Row),
        y: parseInt(obj.Column),
        label: [obj.Data, obj.Media, obj.Code]
    })
    }
});

var chart = Highcharts.chart('tray_container', {
    chart: {
        type: 'heatmap',
        width: 500,
        height: 500,            
    
    },
    title: {
        text: null
    },
    plotOptions: {
        heatmap: {
            borderColor: "black",
            paddingRight: 100
        },
    },
    series: [{
        name: null,
        borderWidth: 1,
        data: parsedData,
        dataLabels: {
            inside: true,//Show 
            enabled: true,
            useHTML: true,
            opacity: 1,
            verticalAlign:'middle',
            align: 'center',
            style: {
                textShadow: 'none',
                HcTextStroke: null,
                display: 'block'
        },
            formatter: function() {
            const label = this.point.label;
            return `${label[1]} <br/> ${label[2]} <br/> ${label[0]}`
            }
        },
    }]
});
}

Answer

You never subscribed to changes of the dropdown, so the data will not change.

  1. Add an onchange listener on the dropdown

     <select id="select_media" onchange="update()" >
    
  2. Put your update logic into the function update() function

function update() {
   // getting drop down list value
   var mediaselect = document.getElementById("select_media").value
   mediaselect_str = String(mediaselect)

   const parsedData = []
   data.forEach(obj => {
       if (obj.Media == mediaselect_str) {
       parsedData.push({
           x: parseInt(obj.Row),
           y: parseInt(obj.Column),
           label: [obj.Data, obj.Media, obj.Code]
       })
       }
   });

   var chart = Highcharts.chart('tray_container', {
       chart: {
           type: 'heatmap',
           width: 500,
           height: 500,            
       
       },
       title: {
           text: null
       },
       plotOptions: {
           heatmap: {
               borderColor: "black",
               paddingRight: 100
           },
       },
       series: [{
           name: null,
           borderWidth: 1,
           data: parsedData,
           dataLabels: {
               inside: true,//Show 
               enabled: true,
               useHTML: true,
               opacity: 1,
               verticalAlign:'middle',
               align: 'center',
               style: {
                   textShadow: 'none',
                   HcTextStroke: null,
                   display: 'block'
           },
               formatter: function() {
               const label = this.point.label;
               return `${label[1]} <br/> ${label[2]} <br/> ${label[0]}`
               }
           },
       }]
   });
  }
  1. Call update() once yourself right at the start, to get the initial chart

See the working fiddle here: http://jsfiddle.net/ran2vz7s/3/