Home > front end >  Automatic update a ChartJs with SQL
Automatic update a ChartJs with SQL

Time:10-01

So I'm trying to do an automatic update for my Chart.Js pie chart, but I'm a bit stuck on how to proceed.

I have in my .php file a MySQL database which is where I got my JS variables from (they are just hardcoded in the example). At the moment when I load the page I do a SQL call, and then run the PieChart(...) function with the retrieved SQL data.

BUT how can I have a button which automatically updates the PieChart, onclick?

I've read that ChartJS has this updater

myLineChart.data.datasets[0].data[2] = 50; // Would update the first dataset's value of 'March' to be 50
myLineChart.update(); // Calling update now animates the position of March from 90 to 50.
 

But how would I use that?

What I have at the moment is a php function that does the SQL call and returns all the information needed for updating the PieChart:

$OverviewResult = pieChartUpdater($FirstItemDD[0]);

This just have to be implemented into these variables

var Passed           = "<?php echo $OverviewResult[0]; ?>";
var Failed           = "<?php echo $OverviewResult[1]; ?>";
var Notrun           = "<?php echo $OverviewResult[2]; ?>";
var Err              = "<?php echo $OverviewResult[3]; ?>";
var Na               = "<?php echo $OverviewResult[4]; ?>";
var PercentagePassed = "<?php echo $OverviewResult[5]; ?>";
var PercentageFailed = "<?php echo $OverviewResult[6]; ?>";
var PercentageNotrun = "<?php echo $OverviewResult[7]; ?>";
var PercentageError  = "<?php echo $OverviewResult[8]; ?>";
var PercentageNa     = "<?php echo $OverviewResult[9]; ?>";

Then the js function PieChart(...) is excecuded.

Should I on a button click maybe make a PieChartUpdater() function, that calles the SQL function and then the update ChartJS part? Or how does it work?

var Passed           = "198";
var Failed           = "37";
var Notrun           = "0";
var Err              = "0";
var Na               = "0";
var PercentagePassed = "84.26";
var PercentageFailed = "15.74";
var PercentageNotrun = "0";
var PercentageError  = "0";
var PercentageNa     = "0";

/**
 * Creates a PieChart overview of results
 *
 * @param {number} pass                 Amount of passed results
 * @param {number} fail                 Amount of failed results
 * @param {number} notRun               Amount of not run results
 * @param {number} err                  Amount of error results
 * @param {number} nA                   Amount of not applicable results
 * @param {number} percentagePassed     Percentage of passed amount
 * @param {number} percentageFailed     Percentage of failed amount
 * @param {number} percentageNotRun     Percentage of not run amount
 * @param {number} percentageError      Percentage of error amount
 * @param {number} percentageNA         Percentage of not applicable amount
 */
function PieChart(pass, fail, notRun, err, nA, percentagePassed, percentageFailed, percentageNotRun, percentageError, percentageNA) {

    window.chartColors = {
        red: '#dc3545',
        green: '#1cc88a',
        blue: '#4e73df',
        yellow: '#f6c23e',
        black: '#5a5c69'
    };

    var config = {
        type: 'pie',
        data: {
            datasets: [{
                data: [
                    nA,
                    err,
                    notRun,
                    fail,
                    pass
                ],
                backgroundColor: [
                    window.chartColors.black,
                    window.chartColors.yellow,
                    window.chartColors.blue,
                    window.chartColors.red,
                    window.chartColors.green,
                ],
                label: 'Dataset 1'
            }],
            labels: [
                percentageNA   "% NA",
                percentageError   "% Error",
                percentageNotRun   "% Not Run",
                percentageFailed   "% Failed",
                percentagePassed   "% Passed"
            ]
        },
        options: {
            responsive: true
        }

    };
    window.onload = function() {
        var ctx = document.getElementById('chart-area').getContext('2d');
        window.myPie = new Chart(ctx, config);
    };
}


PieChart(Passed, Failed, Notrun, Err, Na, PercentagePassed, PercentageFailed, PercentageNotrun, PercentageError, PercentageNa);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<div id="canvas-holder" style="width:50%">
   <div class="chartjs-size-monitor">
      <div class="chartjs-size-monitor-expand">
         <div class=""></div>
      </div>
      <div class="chartjs-size-monitor-shrink">
         <div class=""></div>
      </div>
   </div>
   <canvas id="chart-area" style="display: block; width: 762px; height: 381px;" width="762" height="381" class="chartjs-render-monitor"></canvas>
</div>

What I'm trying to create

enter image description here

CodePudding user response:

Well, you'll have to do a bit of cleanup and new steps:

1. Separate a bit your code into several files:

  • src/config.php : where you put your DB settings, etc.
  • src/data-functions.php : store some DB query functions.
  • index.php : your HTML page.
  • chart-data.php : a service to just retrieve fresh data in JSON.

2. In src/data-functions.php put your logic to retrieve the data in a PHP array:

<?php

/**
 * Get the pie chart data from the DB.
 *
 * @return array
 */
function getPieChartData()
{
    // Do the SQL queries and return an array with the labels,
    // values and colors. We'll be able to convert it to JS later.
    $data = [
        [
            'value' => rand(50, 200),
            'label' => '%.2f%% passed', // sprintf() format to inject pourcentage after.
            'color' => '#1cc88a', // green
        ],
        [
            'value' => rand(0, 30),
            'label' => '%.2f%% failed', // sprintf() format to inject pourcentage after.
            'color' => '#dc3545', // red
        ],
        [
            'value' => rand(0, 3),
            'label' => '%.2f%% not run', // sprintf() format to inject pourcentage after.
            'color' => '#4e73df', // blue
        ],
        [
            'value' => rand(0, 10),
            'label' => '%.2f%% NA', // sprintf() format to inject pourcentage after.
            'color' => '#5a5c69', // gray
        ],
        [
            'value' => rand(0, 2),
            'label' => '%.2f%% Error', // sprintf() format to inject pourcentage after.
            'color' => '#f59f00', // orange
        ],
    ];

    // Calculate the sum of the values so that we can calculate the % to put in the labels.
    $sum = 0;
    foreach ($data as $item) {
        $sum  = $item['value'];
    }

    // Walk accross the array to replace the labels by the calculated % in the label.
    foreach ($data as $i => $item) {
        $data[$i]['label'] = sprintf($item['label'], $item['value'] * 100 / $sum);
    }

    return $data;
}

3. In index.php you generate the HTML and JavaScript code

<?php

require 'src/config.php';
require 'src/data-functions.php';

// Get the data from the DB.
$data = getPieChartData();
// Convert the PHP array to a JS array.
$data_json = json_encode($data);

// The URL to get the data in JSON format.
$data_json_url = '/chart-data.php';

// Print your HTML and JavaScript which will be done once
// at the first page load.
?>
<div id="canvas-holder" style="width:50%">
   <div class="chartjs-size-monitor">
      <div class="chartjs-size-monitor-expand">
         <div class=""></div>
      </div>
      <div class="chartjs-size-monitor-shrink">
         <div class=""></div>
      </div>
   </div>
   <canvas id="chart-area" style="display: block; width: 762px; height: 381px;" width="762" height="381" class="chartjs-render-monitor"></canvas>
   <button id="chart-refresh-button">Refresh data</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script type="text/javascript">
/**
 * @param array data The data for the pie chart.
 * @param string jsonDataUrl The URL of the pie chart JSON data.
 */
function initPieChart(data, jsonDataUrl) {

    var config = {
        type: 'pie',
        data: {
            datasets: [{
                label: 'Dataset 1',
                data: [], // filled later
                backgroundColor: [] // filled later
            }],
            labels: [] // filled later
        },
        options: {
            responsive: true
        }

    };
    
    /**
     * Helper function to set the data values, labels and colors.
     *
     * @param array data The new data to use.
     * @param object chart_data_to_set The chart.js data object to set.
     */
    function setData(data, chart_data_to_set) {
        // Loop over the data to fill the data object for chart.js.
        data.forEach((item, i) => {
            chart_data_to_set.datasets[0].data[i] = item.value;
            chart_data_to_set.datasets[0].backgroundColor[i] = item.color;
            chart_data_to_set.labels[i] = item.label;
        });
    }

    // Fill the config with all our data, labels and colors.
    setData(data, config.data);

    // Once JS is loaded and DOM ready (images & CSS later).
    document.addEventListener("DOMContentLoaded", () => {
        var ctx = document.getElementById('chart-area').getContext('2d');
        var myPie = new Chart(ctx, config);
        
        var updateButton = document.getElementById('chart-refresh-button');
        // Add a click handler on the refresh button.
        updateButton.addEventListener('click', function(event) {
            // Do an Ajax call to the server to just get the fresh data.
            fetch(jsonDataUrl).then(response => {
                return response.json();
            })
            .then(freshData => {
                // Update the chart data with the fresh data.
                setData(freshData, myPie.data);
                myPie.update();
            })
            .catch(error => {
                console.log('An error occured while fetching data from the server', error);
            });
        });
    });
}

initPieChart(<?php echo $data_json; ?>, '<?php echo $data_json_url; ?>');

</script>

As you can see, the PHP array is converted to a JavaScript array with the help of json_encode() and is printed in place of $data_json inside the HTML/JS output. This way you don't need all the JS variables which where confusing and messing up the code. This solution is more generic since you could change your data in PHP and all the rest would update without changing the JS code.

4. Create chart-data.php to return the fresh data in JSON

<?php

require 'src/config.php';
require 'src/data-functions.php';

// We won't print any HTML but just return the data in JSON.
$data = getPieChartData();
// Sent the correct MIME type for JSON and return the fresh data.
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data);
  • Related