Unable to change y-axis value dynamically based on data for Stacked bar chart in reactjs

1.9k Views Asked by At

My Objective to show the y-axis value dynamically in the chart. If my data contains below 100 i.e(highest value in data = 75) then it should show 80 as highest number in y-axis. it should not show 500 in the y-axis.

<Bar
    data={this.state.data}
    width={400}
    height='150'
    options={{
        tooltips: {
            mode: 'point',
            intersect: false,
        },

        responsive: true,
        scales: {
        xAxes: [{
                stacked: true,
            }],
            yAxes: [{
  stacked: false,
  ticks: {
    beginAtZero: true,
    min: 0,
    max: 500
  }
}, {
  id: "bar-stacked",
  stacked: true,
  display: false,
  ticks: {
    beginAtZero: true,
    min: 0,
    max: 500
  },
  type: 'linear'
}]
        }
    }}
/>


Is it possible to make it dynamic? If yes, Can anyone help me in this query?

1

There are 1 best solutions below

6
On

To dynamically compute the ticks you need a couple things.

  1. A utility to precompute and find the maximum value in your data.
  2. A utility to compute the maximum axis tick.

To find the maximum value in the array of (presumably objects) data you can do something similar to the following.

const findMaxVal = (arr, field) => Math.max(...arr.map((el) => el[field]));

const data = [
  {
    id: 0,
    customField: 23
  },
  {
    id: 1,
    customField: 31
  },
  {
    id: 2,
    customField: 29
  },
  {
    id: 3,
    customField: 7
  },
  {
    id: 4,
    customField: 13
  }
];

const findMaxVal = (arr, field) => Math.max(...arr.map((el) => el[field]));

console.log(findMaxVal(data, "customField")); // 31

[edit]

You mention in comments your data has this shape

[
  {xaxis: "bar-stacked", data:[0,12,19,50,2,30,14]},
  {yaxis: "bar-stacked", data:[2,4,15,29,10,3,1]},
]

To find the maximum value in the data you can simply spread data into Math.max.

const findMaxVal = data => Math.max(...data);

const data = [
      {xaxis: "bar-stacked", data:[0,12,19,50,2,30,14]},
      {yaxis: "bar-stacked", data:[2,4,15,29,10,3,1]},
    ];

const findMaxVal = data => Math.max(...data);

console.log(findMaxVal(data[0].data)); // 50
console.log(findMaxVal(data[1].data)); // 29

[/edit]

To compute the max tick you can compute the next "chunked" tick after the maximum computed from data with something similar to:

const computeTicks = (val, chunk = 10) => Math.floor(val / chunk) * chunk + chunk;

or

const computeTicks = (val, chunk = 10) => Math.ceil(val / chunk) * chunk;

The difference between the two is what to "round" to if the value is even divided by the chunk amount, i.e. if data max 80 should have max tick of 80 or 90. This first would yield 90 while the second would yield 80.

const computeTicks = (val, chunk = 10) => Math.floor(val / chunk) * chunk + chunk;

console.log(computeTicks(13)); // 20
console.log(computeTicks(19, 10)); // 20
console.log(computeTicks(20, 10)); // 30

console.log(computeTicks(13, 5)); // 15
console.log(computeTicks(13, 6)); // 18
console.log(computeTicks(18, 6)); // 24
console.log(computeTicks(19, 6)); // 24

Put these two together to compute the ticks to display in the graph.

const dataMax = findMaxVal(data, 'fieldIwantMaxOf'); // <-- compute max val before JSX return

...

<Bar
  ...
  options={{
    ...,
    scales: {
      ...,
      yAxes: [
        {
          ...,
          ticks: {
            ...,
            max: computeTicks(dataMax, 10) || 500, // <-- compute max or use default 500
          }
        },
        ...,
      ]
    }
  }}
/>