Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to hide specific data element #9450

Merged
merged 1 commit into from Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 10 additions & 4 deletions docs/developers/api.md
Expand Up @@ -152,20 +152,26 @@ Returns the stored visibility state of an data index for all datasets. Set by [t
var visible = chart.getDataVisibility(2);
```

## hide(datasetIndex)
## hide(datasetIndex, dataIndex?)

Sets the visibility for the given dataset to false. Updates the chart and animates the dataset with `'hide'` mode. This animation can be configured under the `hide` key in animation options. Please see [animations](../configuration/animations.md) docs for more details.
If dataIndex is not specified, sets the visibility for the given dataset to false. Updates the chart and animates the dataset with `'hide'` mode. This animation can be configured under the `hide` key in animation options. Please see [animations](../configuration/animations.md) docs for more details.

If dataIndex is specified, sets the hidden flag of that element to true and updates the chart.

```javascript
chart.hide(1); // hides dataset at index 1 and does 'hide' animation.
chart.hide(0, 2); // hides the data element at index 2 of the first dataset.
```

## show(datasetIndex)
## show(datasetIndex, dataIndex?)

If dataIndex is not specified, sets the visibility for the given dataset to true. Updates the chart and animates the dataset with `'show'` mode. This animation can be configured under the `show` key in animation options. Please see [animations](../configuration/animations.md) docs for more details.

Sets the visibility for the given dataset to true. Updates the chart and animates the dataset with `'show'` mode. This animation can be configured under the `show` key in animation options. Please see [animations](../configuration/animations.md) docs for more details.
If dataIndex is specified, sets the hidden flag of that element to false and updates the chart.

```javascript
chart.show(1); // shows dataset at index 1 and does 'show' animation.
chart.show(0, 2); // shows the data element at index 2 of the first dataset.
```

## setActiveElements(activeElements)
Expand Down
24 changes: 24 additions & 0 deletions docs/samples/other-charts/doughnut.md
Expand Up @@ -48,6 +48,30 @@ const actions = [
}
}
},
{
name: 'Hide(0)',
handler(chart) {
chart.hide(0);
}
},
{
name: 'Show(0)',
handler(chart) {
chart.show(0);
}
},
{
name: 'Hide (0, 1)',
handler(chart) {
chart.hide(0, 1);
}
},
{
name: 'Show (0, 1)',
handler(chart) {
chart.show(0, 1);
}
},
{
name: 'Remove Dataset',
handler(chart) {
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/controller.doughnut.js
Expand Up @@ -145,7 +145,7 @@ export default class DoughnutController extends DatasetController {
const opts = me.options;
const meta = me._cachedMeta;
const circumference = me._getCircumference();
if ((reset && opts.animation.animateRotate) || !this.chart.getDataVisibility(i) || meta._parsed[i] === null) {
if ((reset && opts.animation.animateRotate) || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) {
return 0;
}
return me.calculateCircumference(meta._parsed[i] * circumference / TAU);
Expand Down Expand Up @@ -203,7 +203,7 @@ export default class DoughnutController extends DatasetController {

for (i = 0; i < metaData.length; i++) {
const value = meta._parsed[i];
if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i)) {
if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) {
total += Math.abs(value);
}
}
Expand Down
26 changes: 15 additions & 11 deletions src/core/core.controller.js
Expand Up @@ -7,7 +7,7 @@ import PluginService from './core.plugins';
import registry from './core.registry';
import Config, {determineAxis, getIndexAxis} from './core.config';
import {retinaScale, _isDomSupported} from '../helpers/helpers.dom';
import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef, setsEqual} from '../helpers/helpers.core';
import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef, setsEqual, defined} from '../helpers/helpers.core';
import {clearCanvas, clipArea, unclipArea, _isPointInArea} from '../helpers/helpers.canvas';
// @ts-ignore
import {version} from '../../package.json';
Expand Down Expand Up @@ -794,25 +794,29 @@ class Chart {
/**
* @private
*/
_updateDatasetVisibility(datasetIndex, visible) {
_updateVisibility(datasetIndex, dataIndex, visible) {
const me = this;
const mode = visible ? 'show' : 'hide';
const meta = me.getDatasetMeta(datasetIndex);
const anims = meta.controller._resolveAnimations(undefined, mode);
me.setDatasetVisibility(datasetIndex, visible);

// Animate visible state, so hide animation can be seen. This could be handled better if update / updateDataset returned a Promise.
anims.update(meta, {visible});

me.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : undefined);
if (defined(dataIndex)) {
meta.data[dataIndex].hidden = !visible;
me.update();
} else {
me.setDatasetVisibility(datasetIndex, visible);
// Animate visible state, so hide animation can be seen. This could be handled better if update / updateDataset returned a Promise.
anims.update(meta, {visible});
me.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : undefined);
}
}

hide(datasetIndex) {
this._updateDatasetVisibility(datasetIndex, false);
hide(datasetIndex, dataIndex) {
this._updateVisibility(datasetIndex, dataIndex, false);
}

show(datasetIndex) {
this._updateDatasetVisibility(datasetIndex, true);
show(datasetIndex, dataIndex) {
this._updateVisibility(datasetIndex, dataIndex, true);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/core/core.datasetController.js
Expand Up @@ -701,6 +701,9 @@ export default class DatasetController {

for (i = start; i < start + count; ++i) {
const element = elements[i];
if (element.hidden) {
continue;
}
if (element.active) {
active.push(element);
} else {
Expand Down
42 changes: 42 additions & 0 deletions test/fixtures/controller.doughnut/doughnut-hidden-single.js
@@ -0,0 +1,42 @@
module.exports = {
config: {
type: 'doughnut',
data: {
labels: ['A', 'B', 'C', 'D', 'E'],
datasets: [{
data: [1, 5, 10, 50, 100],
backgroundColor: [
'rgba(255, 99, 132, 0.8)',
'rgba(54, 162, 235, 0.8)',
'rgba(255, 206, 86, 0.8)',
'rgba(75, 192, 192, 0.8)',
'rgba(153, 102, 255, 0.8)'
],
}, {
data: [1, 5, 10, 50, 100],
backgroundColor: [
'rgba(255, 99, 132, 0.8)',
'rgba(54, 162, 235, 0.8)',
'rgba(255, 206, 86, 0.8)',
'rgba(75, 192, 192, 0.8)',
'rgba(153, 102, 255, 0.8)'
],
}]
},
options: {
responsive: false,
plugins: {
legend: false,
title: false,
tooltip: false,
filler: false
}
},
},
options: {
run(chart) {
chart.hide(0, 4);
chart.hide(1, 2);
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions types/index.esm.d.ts
Expand Up @@ -505,8 +505,8 @@ export declare class Chart<
setDatasetVisibility(datasetIndex: number, visible: boolean): void;
toggleDataVisibility(index: number): void;
getDataVisibility(index: number): boolean;
hide(datasetIndex: number): void;
show(datasetIndex: number): void;
hide(datasetIndex: number, dataIndex?: number): void;
show(datasetIndex: number, dataIndex?: number): void;

getActiveElements(): ActiveElement[];
setActiveElements(active: ActiveDataPoint[]): void;
Expand Down