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:
Jukka Kurkela 2020-11-06 15:05:56 +02:00 committed by GitHub
parent afbe03cce4
commit 10ffe753d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 10 deletions

View File

@ -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] = {

View File

@ -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);
}

View File

@ -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];