Legend onClick callback supports arrow functions (#7410)

#7409 Legend callbacks support arrow functions
The `Legend` is no longer implicitly found through `this` and instead
passed as an explicit argument to the callback functions.
This commit is contained in:
Evert Timberg 2020-05-24 10:28:41 -04:00 committed by GitHub
parent e0f44051b5
commit 13b8924ac3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 45 additions and 44 deletions

View File

@ -14,9 +14,9 @@ The legend configuration is passed into the `options.legend` namespace. The glob
| `position` | `string` | `'top'` | Position of the legend. [more...](#position)
| `align` | `string` | `'center'` | Alignment of the legend. [more...](#align)
| `fullWidth` | `boolean` | `true` | Marks that this box should take the full width of the canvas (pushing down other boxes). This is unlikely to need to be changed in day-to-day use.
| `onClick` | `function` | | A callback that is called when a click event is registered on a label item.
| `onHover` | `function` | | A callback that is called when a 'mousemove' event is registered on top of a label item.
| `onLeave` | `function` | | A callback that is called when a 'mousemove' event is registered outside of a previously hovered label item.
| `onClick` | `function` | | A callback that is called when a click event is registered on a label item. Arguments: `[event, legendItem, legend]`.
| `onHover` | `function` | | A callback that is called when a 'mousemove' event is registered on top of a label item. Arguments: `[event, legendItem, legend]`.
| `onLeave` | `function` | | A callback that is called when a 'mousemove' event is registered outside of a previously hovered label item. Arguments: `[event, legendItem, legend]`.
| `reverse` | `boolean` | `false` | Legend will show datasets in reverse order.
| `labels` | `object` | | See the [Legend Label Configuration](#legend-label-configuration) section below.
| `rtl` | `boolean` | | `true` for rendering the legends from right to left.
@ -134,16 +134,16 @@ It can be common to want to trigger different behaviour when clicking an item in
The default legend click handler is:
```javascript
function(e, legendItem) {
var index = legendItem.datasetIndex;
var ci = this.chart;
var meta = ci.getDatasetMeta(index);
// See controller.isDatasetVisible comment
meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
// We hid a dataset ... rerender the chart
ci.update();
function(e, legendItem, legend) {
const index = legendItem.datasetIndex;
const ci = legend.chart;
if (ci.isDatasetVisible(index)) {
ci.hide(index);
legendItem.hidden = true;
} else {
ci.show(index);
legendItem.hidden = false;
}
}
```
@ -151,14 +151,14 @@ Lets say we wanted instead to link the display of the first two datasets. We cou
```javascript
var defaultLegendClickHandler = Chart.defaults.legend.onClick;
var newLegendClickHandler = function (e, legendItem) {
var newLegendClickHandler = function (e, legendItem, legend) {
var index = legendItem.datasetIndex;
if (index > 1) {
// Do the original logic
defaultLegendClickHandler(e, legendItem);
} else {
let ci = this.chart;
let ci = legend.chart;
[
ci.getDatasetMeta(0),
ci.getDatasetMeta(1)

View File

@ -7,8 +7,8 @@ The following properties define how the chart interacts with events.
| Name | Type | Default | Description
| ---- | ---- | ------- | -----------
| `events` | `string[]` | `['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove']` | The `events` option defines the browser events that the chart should listen to for tooltips and hovering. [more...](#event-option)
| `onHover` | `function` | `null` | Called when any of the events fire. Called in the context of the chart and passed the event and an array of active elements (bars, points, etc).
| `onClick` | `function` | `null` | Called if the event is of type `'mouseup'` or `'click'`. Called in the context of the chart and passed the event and an array of active elements.
| `onHover` | `function` | `null` | Called when any of the events fire. Passed the event, an array of active elements (bars, points, etc), and the chart.
| `onClick` | `function` | `null` | Called if the event is of type `'mouseup'` or `'click'`. Passed the event, an array of active elements, and the chart.
## Event Option
For example, to have the chart only respond to click events, you could do:

View File

@ -157,6 +157,7 @@ Animation system was completely rewritten in Chart.js v3. Each property can now
* `{mode: 'single'}` was replaced with `{mode: 'nearest', intersect: true}`
* `modes['X-axis']` was replaced with `{mode: 'index', intersect: false}`
* `options.onClick` is now limited to the chart area
* `options.onClick` and `options.onHover` now receive the `chart` instance as a 3rd argument
#### Ticks
@ -279,6 +280,8 @@ The following properties and methods were removed:
* `IPlugin.afterScaleUpdate`. Use `afterLayout` instead
* `Legend.margins` is now private
* Legend `onClick`, `onHover`, and `onLeave` options now receive the legend as the 3rd argument in addition to implicitly via `this`
* Legend `onClick`, `onHover`, and `onLeave` options now receive a wrapped `event` as the first parameter. The previous first parameter value is accessible via `event.native`.
* `Title.margins` is now private
* The tooltip item's `x` and `y` attributes were removed. Use `datasetIndex` and `index` to get the element and any corresponding data from it

View File

@ -71,12 +71,12 @@
return labels;
}
},
onClick: function(mouseEvent, legendItem) {
onClick: function(mouseEvent, legendItem, legend) {
// toggle the visibility of the dataset from what it currently is
this.chart.getDatasetMeta(
legend.chart.getDatasetMeta(
legendItem.datasetIndex
).hidden = this.chart.isDatasetVisible(legendItem.datasetIndex);
this.chart.update();
).hidden = legend.chart.isDatasetVisible(legendItem.datasetIndex);
legend.chart.update();
}
},
tooltips: {

View File

@ -75,7 +75,7 @@
label: 'New dataset ' + config.data.datasets.length,
};
for (var index = 0; index < config.data.labels.length; ++index) {
for (var index = 0; index < 10; ++index) {
newDataset.data.push(randomScalingFactor());
var colorName = colorNames[index % colorNames.length];

View File

@ -47,9 +47,9 @@ defaults.set('doughnut', {
}
},
onClick(e, legendItem) {
this.chart.toggleDataVisibility(legendItem.index);
this.chart.update();
onClick(e, legendItem, legend) {
legend.chart.toggleDataVisibility(legendItem.index);
legend.chart.update();
}
},

View File

@ -55,9 +55,9 @@ defaults.set('polarArea', {
}
},
onClick(e, legendItem) {
this.chart.toggleDataVisibility(legendItem.index);
this.chart.update();
onClick(e, legendItem, legend) {
legend.chart.toggleDataVisibility(legendItem.index);
legend.chart.update();
}
},

View File

@ -1108,12 +1108,12 @@ export default class Chart {
// Invoke onHover hook
// Need to call with native event here to not break backwards compatibility
callCallback(options.onHover || options.hover.onHover, [e.native, me.active], me);
callCallback(options.onHover || options.hover.onHover, [e.native, me.active, me], me);
if (e.type === 'mouseup' || e.type === 'click') {
if (options.onClick && _isPointInArea(e, me.chartArea)) {
if (_isPointInArea(e, me.chartArea)) {
// Use e.native here for backwards compatibility
options.onClick.call(me, e.native, me.active);
callCallback(options.onClick, [e, me.active, me], me);
}
}

View File

@ -19,9 +19,9 @@ defaults.set('legend', {
weight: 1000,
// a callback that will handle
onClick(e, legendItem) {
onClick(e, legendItem, legend) {
const index = legendItem.datasetIndex;
const ci = this.chart;
const ci = legend.chart;
if (ci.isDatasetVisible(index)) {
ci.hide(index);
legendItem.hidden = true;
@ -659,21 +659,19 @@ export class Legend extends Element {
const hoveredItem = me._getLegendItemAt(e.x, e.y);
if (type === 'click') {
if (hoveredItem && opts.onClick) {
// use e.native for backwards compatibility
opts.onClick.call(me, e.native, hoveredItem);
if (hoveredItem) {
call(opts.onClick, [e, hoveredItem, me], me);
}
} else {
if (opts.onLeave && hoveredItem !== me._hoveredItem) {
if (me._hoveredItem) {
opts.onLeave.call(me, e.native, me._hoveredItem);
call(opts.onLeave, [e, me._hoveredItem, me], me);
}
me._hoveredItem = hoveredItem;
}
if (opts.onHover && hoveredItem) {
// use e.native for backwards compatibility
opts.onHover.call(me, e.native, hoveredItem);
if (hoveredItem) {
call(opts.onHover, [e, hoveredItem, me], me);
}
}
}

View File

@ -147,12 +147,12 @@ describe('Default Configs', function() {
spyOn(chart, 'update').and.callThrough();
var legendItem = chart.legend.legendItems[0];
config.legend.onClick.call(chart.legend, null, legendItem);
config.legend.onClick(null, legendItem, chart.legend);
expect(chart.getDataVisibility(0)).toBe(false);
expect(chart.update).toHaveBeenCalled();
config.legend.onClick.call(chart.legend, null, legendItem);
config.legend.onClick(null, legendItem, chart.legend);
expect(chart.getDataVisibility(0)).toBe(true);
});
});
@ -243,12 +243,12 @@ describe('Default Configs', function() {
spyOn(chart, 'update').and.callThrough();
var legendItem = chart.legend.legendItems[0];
config.legend.onClick.call(chart.legend, null, legendItem);
config.legend.onClick(null, legendItem, chart.legend);
expect(chart.getDataVisibility(0)).toBe(false);
expect(chart.update).toHaveBeenCalled();
config.legend.onClick.call(chart.legend, null, legendItem);
config.legend.onClick(null, legendItem, chart.legend);
expect(chart.getDataVisibility(0)).toBe(true);
});
});