Pie chart.js - display a no data held message

10,805

Solution 1

Here an example working with chart.js 2.8.0

<canvas id="pieChartExample01" width="25" height="25"></canvas>
<div id="no-data">Nothing to display</div>

...
options: {
  title: {
    display: false,
    text: 'Overall Activity'
  },
  animation: {
    onComplete: function(animation) {
      var firstSet = animation.chart.config.data.datasets[0].data,
        dataSum = firstSet.reduce((accumulator, currentValue) => accumulator + currentValue);

      if (typeof firstSet !== "object" || dataSum === 0) {
        document.getElementById('no-data').style.display = 'block';
        document.getElementById('pieChartExample01').style.display = 'none'
      }
    }
  }
}

Fiddle

Solution 2

Use this plugin I slightly modified which checks if each dataset item is zero:

<script>
    Chart.plugins.register({
        afterDraw: function(chart) {
            if (chart.data.datasets[0].data.every(item => item === 0)) {
                let ctx = chart.chart.ctx;
                let width = chart.chart.width;
                let height = chart.chart.height;

                chart.clear();
                ctx.save();
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillText('No data to display', width / 2, height / 2);
                ctx.restore();
            }
        }
    });
</script>

With this, if all dataset items are 0, it will display No data to display in place of the chart.

Solution 3

For React (react-chartjs-2)

Use this plugin

const plugins = [
  {
    afterDraw: function (chart) {
      console.log(chart);
      if (chart.data.datasets[0].data.length < 1) {
        let ctx = chart.ctx;
        let width = chart.width;
        let height = chart.height;
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.font = "30px Arial";
        ctx.fillText("No data to display", width / 2, height / 2);
        ctx.restore();
      }
    },
  },
];

Use this plugin

<Line height={120} data={props.data} options={options} plugins={plugins} />
<Pie height={320} width={500} data={props.data} options={options} plugins={plugins} />
Share:
10,805
user1261774
Author by

user1261774

Updated on June 23, 2022

Comments

  • user1261774
    user1261774 almost 2 years

    I'm using chart.js Version: 2.8.0 to display a bar chart and a pie chart.

    The non-empty bar and pie charts display as I want.

    However, when the bar and pie charts are empty or have zero data to display, is there a standardised option to display a "No data to display!" message for both the bar and pie charts that can be shown in place of the empty or zero data.

    I've searched google for a plugin and SO for a solution, but the options I've found either don't work at all or don't work for the latest version of chartjs.

    Here is my empty pie chart:

    new Chart(document.getElementById('pieChartExample01'), {
        type: 'pie',
        data: {
            labels: [
                'Views',
                'Print Requests',
                'PDF Downloads',
                'DOCX Downloads',
            ],
            datasets: [{
                backgroundColor: [
                    'rgba(71, 101, 160, 0.3)',  // #4765a0.
                    'rgba(0, 0, 0, 0.3)',  // #000000.
                    'rgba(52, 137, 219, 0.3)',  // #3489db.
                    'rgba(179, 179, 179, 0.3)',  // #b3b3b3.
                ],
                hoverBackgroundColor: [
                    'rgba(71, 101, 160, 0.6)',  // #4765a0.
                    'rgba(0, 0, 0, 0.6)',  // #000000.
                    'rgba(52, 137, 219, 0.6)',  // #3489db.
                    'rgba(179, 179, 179, 0.6)',  // #b3b3b3.
                ],
                borderWidth: 1,
                hoverBorderWidth: 2,
                borderColor: [
                    'rgba(71, 101, 160, 1)',  // #4765a0.
                    'rgba(0, 0, 0, 1)',  // #000000.
                    'rgba(52, 137, 219, 1)',  // #3489db.
                    'rgba(179, 179, 179, 1)',  // #b3b3b3.
                ],
                borderAlign: 'inner',
                data: [0, 0, 0, 0]
          }]
        },
        options: {
            title: {
              display: false,
              text: 'Overall Activity'
            }
        }
    });
    <canvas id="pieChartExample01" width="25" height="25"></canvas>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

    This is what I would like the empty pie chart to display as (preferably with the labels):

    enter image description here

    UPDATE TO ANSWER - 13th April, 2019

    Using the answer provided by Core972, I decided to extrapolate the accepted answer so that the message of choice can be displayed over a bar chart and a pie chart with the data labels displayed rather than just a blank canvas.

    Here's the solution that I came up with that works with pie and bar charts.

    I haven't tested the other types of charts, but I'm presuming they would work with the same approach.

    A few pointers to note:

    1. When there is zero data to display, the borders must also be zero, otherwise an annoying border displayed as a single line is displayed. Use a simple if else condition to hide show the borders if necessary.

    2. Use an if else condition to display / hide the message. If there is data, hide the message, else display the message if data is zero.

    3. I've only tested this approach with Chrome & Firefox and seems to work OK.

    I hope that this can help someone! Enjoy!

    PIE CHART WITH DATA LABELS DISPLAYED AND A FLOATING MESSAGE:

    new Chart(document.getElementById('pieChartExample01'), {
        type: 'pie',
        data: {
            labels: [
                'Views',
                'Print Requests',
                'PDF Downloads',
                'DOCX Downloads',
            ],
            datasets: [{
                backgroundColor: [
                    'rgba(71, 101, 160, 0.3)',  // #4765a0.
                    'rgba(0, 0, 0, 0.3)',  // #000000.
                    'rgba(52, 137, 219, 0.3)',  // #3489db.
                    'rgba(179, 179, 179, 0.3)',  // #b3b3b3.
                ],
                hoverBackgroundColor: [
                    'rgba(71, 101, 160, 0.6)',  // #4765a0.
                    'rgba(0, 0, 0, 0.6)',  // #000000.
                    'rgba(52, 137, 219, 0.6)',  // #3489db.
                    'rgba(179, 179, 179, 0.6)',  // #b3b3b3.
                ],
                borderWidth: 0,
                hoverBorderWidth: 0,
                borderColor: [
                    'rgba(71, 101, 160, 1)',  // #4765a0.
                    'rgba(0, 0, 0, 1)',  // #000000.
                    'rgba(52, 137, 219, 1)',  // #3489db.
                    'rgba(179, 179, 179, 1)',  // #b3b3b3.
                ],
                borderAlign: 'inner',
                data: [0, 0, 0, 0]
          }]
        },
        options: {
            title: {
              display: false,
              text: 'Overall Activity'
            }
        }
    });
    <div style="width: 100%; height: 100%; position: relative;">
        <div style="text-align: center; width: 100%; height: 100%; position: absolute; left: 0; top: 100px; z-index: 20;">
            <b>No data for you today!</b>
        </div>
        <canvas id="pieChartExample01" width="25" height="25"></canvas>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
    </div>
  • user1261774
    user1261774 about 5 years
    You have misread the question! When there is no data to display, I want a message displayed.
  • amprie286
    amprie286 over 3 years
    This is the perfect answer
  • Tanckom
    Tanckom over 3 years
    Love this answer! Instead of updating the whole Chart class, you can also do it directly on a new single chart instance like let chart = new Chart(ctx, { plugins: [ { afterDraw: function(chart){...} } ]}
  • Jayanth Kumar T
    Jayanth Kumar T over 2 years
    Doesn't work in latest version 3.5.1
  • zlatanned
    zlatanned about 2 years
    Thanks stardust4891 and @Tanckom This worked like a charm.