mirror of
https://github.com/chartjs/Chart.js.git
synced 2024-10-06 12:19:08 +02:00
When data is removed, remove from stacks too (#8013)
* When data is removed, remove from stacks too * Remove unreferenced metasets
This commit is contained in:
parent
afbe03cce4
commit
10ffe753d9
@ -362,12 +362,27 @@ class Chart {
|
||||
me._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_removeUnreferencedMetasets() {
|
||||
const me = this;
|
||||
const datasets = me.data.datasets;
|
||||
me._metasets.forEach((meta, index) => {
|
||||
if (datasets.filter(x => x === meta._dataset).length === 0) {
|
||||
me._destroyDatasetMeta(index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
buildOrUpdateControllers() {
|
||||
const me = this;
|
||||
const newControllers = [];
|
||||
const datasets = me.data.datasets;
|
||||
let i, ilen;
|
||||
|
||||
me._removeUnreferencedMetasets();
|
||||
|
||||
for (i = 0, ilen = datasets.length; i < ilen; i++) {
|
||||
const dataset = datasets[i];
|
||||
let meta = me.getDatasetMeta(i);
|
||||
@ -694,7 +709,7 @@ class Chart {
|
||||
const me = this;
|
||||
const dataset = me.data.datasets[datasetIndex];
|
||||
const metasets = me._metasets;
|
||||
let meta = metasets.filter(x => x._dataset === dataset).pop();
|
||||
let meta = metasets.filter(x => x && x._dataset === dataset).pop();
|
||||
|
||||
if (!meta) {
|
||||
meta = metasets[datasetIndex] = {
|
||||
|
@ -191,6 +191,13 @@ function createDataContext(parent, index, point, element) {
|
||||
});
|
||||
}
|
||||
|
||||
function clearStacks(meta, items) {
|
||||
items = items || meta._parsed;
|
||||
items.forEach((parsed) => {
|
||||
delete parsed._stacks[meta.vScale.id][meta.index];
|
||||
});
|
||||
}
|
||||
|
||||
const optionKeys = (optionNames) => isArray(optionNames) ? optionNames : Object.keys(optionNames);
|
||||
const optionKey = (key, active) => active ? 'hover' + _capitalize(key) : key;
|
||||
const isDirectUpdateMode = (mode) => mode === 'reset' || mode === 'none';
|
||||
@ -293,9 +300,13 @@ export default class DatasetController {
|
||||
* @private
|
||||
*/
|
||||
_destroy() {
|
||||
const meta = this._cachedMeta;
|
||||
if (this._data) {
|
||||
unlistenArrayEvents(this._data, this);
|
||||
}
|
||||
if (meta._stacked) {
|
||||
clearStacks(meta);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,9 +368,7 @@ export default class DatasetController {
|
||||
if (meta.stack !== dataset.stack) {
|
||||
stackChanged = true;
|
||||
// remove values from old stack
|
||||
meta._parsed.forEach((parsed) => {
|
||||
delete parsed._stacks[meta.vScale.id][meta.index];
|
||||
});
|
||||
clearStacks(meta);
|
||||
meta.stack = dataset.stack;
|
||||
}
|
||||
|
||||
@ -958,15 +967,13 @@ export default class DatasetController {
|
||||
*/
|
||||
_resyncElements() {
|
||||
const me = this;
|
||||
const meta = me._cachedMeta;
|
||||
const numMeta = meta.data.length;
|
||||
const numMeta = me._cachedMeta.data.length;
|
||||
const numData = me._data.length;
|
||||
|
||||
if (numData > numMeta) {
|
||||
me._insertElements(numMeta, numData - numMeta);
|
||||
} else if (numData < numMeta) {
|
||||
meta.data.splice(numData, numMeta - numData);
|
||||
meta._parsed.splice(numData, numMeta - numData);
|
||||
me._removeElements(numData, numMeta - numData);
|
||||
}
|
||||
// Re-parse the old elements (new elements are parsed in _insertElements)
|
||||
me.parse(0, Math.min(numData, numMeta));
|
||||
@ -1002,10 +1009,14 @@ export default class DatasetController {
|
||||
*/
|
||||
_removeElements(start, count) {
|
||||
const me = this;
|
||||
const meta = me._cachedMeta;
|
||||
if (me._parsing) {
|
||||
me._cachedMeta._parsed.splice(start, count);
|
||||
const removed = meta._parsed.splice(start, count);
|
||||
if (meta._stacked) {
|
||||
clearStacks(meta, removed);
|
||||
}
|
||||
}
|
||||
me._cachedMeta.data.splice(start, count);
|
||||
meta.data.splice(start, count);
|
||||
}
|
||||
|
||||
|
||||
|
@ -519,6 +519,50 @@ describe('Chart.DatasetController', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should re-synchronize stacks when data is removed', function() {
|
||||
var chart = acquireChart({
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ['a', 'b'],
|
||||
datasets: [{
|
||||
data: [1, 10],
|
||||
stack: '1'
|
||||
}, {
|
||||
data: [2, 20],
|
||||
stack: '2'
|
||||
}, {
|
||||
data: [3, 30],
|
||||
stack: '1'
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
expect(chart._stacks).toEqual({
|
||||
'x.y.1.bar': {
|
||||
0: {0: 1, 2: 3},
|
||||
1: {0: 10, 2: 30}
|
||||
},
|
||||
'x.y.2.bar': {
|
||||
0: {1: 2},
|
||||
1: {1: 20}
|
||||
}
|
||||
});
|
||||
|
||||
chart.data.datasets[2].data = [4];
|
||||
chart.update();
|
||||
|
||||
expect(chart._stacks).toEqual({
|
||||
'x.y.1.bar': {
|
||||
0: {0: 1, 2: 4},
|
||||
1: {0: 10}
|
||||
},
|
||||
'x.y.2.bar': {
|
||||
0: {1: 2},
|
||||
1: {1: 20}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should cleanup attached properties when the reference changes or when the chart is destroyed', function() {
|
||||
var data0 = [0, 1, 2, 3, 4, 5];
|
||||
var data1 = [6, 7, 8];
|
||||
|
Loading…
Reference in New Issue
Block a user