diff --git a/docs/guide/options.md b/docs/guide/options.md index eae6097d9..e40427d5a 100644 --- a/docs/guide/options.md +++ b/docs/guide/options.md @@ -116,6 +116,7 @@ In addition to [chart](#chart) * `id`: the annotation id * `element`: the annotation element +* `elements`: the array which contains the already created annotation elements. * `type`: `'annotation'` The [annotation](#annotation) option context is passed to scriptable options in all other cases, except when resolving `id`, `type` or adjusting scale ranges. The same values resolved in `afterDataLimits` with [chart](#chart) context are again evaluated in `afterUpdate` with [annotation](#annotation) context. diff --git a/src/elements.js b/src/elements.js index 08db4604a..d3dd19e90 100644 --- a/src/elements.js +++ b/src/elements.js @@ -52,7 +52,7 @@ export function updateElements(chart, state, options, mode) { for (let i = 0; i < annotations.length; i++) { const annotationOptions = annotations[i]; const element = getOrCreateElement(elements, i, annotationOptions.type); - const resolver = annotationOptions.setContext(getContext(chart, element, annotationOptions)); + const resolver = annotationOptions.setContext(getContext(chart, element, elements, annotationOptions)); const properties = element.resolveElementProperties(chart, resolver); properties.skip = toSkip(properties); @@ -142,9 +142,12 @@ function resolveObj(resolver, defs) { return result; } -function getContext(chart, element, annotation) { +function getContext(chart, element, elements, annotation) { return element.$context || (element.$context = Object.assign(Object.create(chart.getContext()), { element, + get elements() { + return elements.filter((el) => el && el.options); + }, id: annotation.id, type: 'annotation' })); diff --git a/test/specs/annotation.spec.js b/test/specs/annotation.spec.js index 6d1d49b35..90c9c5dc0 100644 --- a/test/specs/annotation.spec.js +++ b/test/specs/annotation.spec.js @@ -211,4 +211,94 @@ describe('Annotation plugin', function() { expect(element.options.drawTime).toBe(chart.options.plugins.annotation.annotations.label.drawTime); }); }); + + describe('context', function() { + it('should contain the loaded elements', function() { + const counts = []; + const annotations = []; + for (let i = 0; i < 5; i++) { + annotations.push({ + type: 'label', + content: 'test', + display(context) { + expect(context.elements.length).toBe(i); + counts.push(i); + } + }); + } + acquireChart({ + type: 'line', + options: { + plugins: { + annotation: { + annotations + } + } + } + }); + expect(counts).toEqual([0, 1, 2, 3, 4]); + }); + it('should contain the loaded elements after update', function() { + const counts = []; + const annotations = []; + for (let i = 0; i < 5; i++) { + annotations.push({ + type: 'label', + content: 'test', + display(context) { + expect(context.elements.length).toBe(i); + counts.push(i); + } + }); + } + const chart = acquireChart({ + type: 'line', + options: { + plugins: { + annotation: { + annotations + } + } + } + }); + counts.splice(0, counts.length); + chart.update(); + expect(counts).toEqual([0, 1, 2, 3, 4]); + }); + + it('should contain the loaded elements after reducing annotations and chart update', function() { + const counts = []; + const annotations = []; + for (let i = 0; i < 5; i++) { + annotations.push({ + type: 'label', + content: 'test', + display(context) { + const check = context.chart.options.plugins.annotation.annotations.length < 5; + if (check) { + expect(context.elements.length).toBe(i - 2); + counts.push(i); + } + } + }); + } + const chart = acquireChart({ + type: 'line', + options: { + plugins: { + annotation: { + annotations + } + } + } + }); + counts.splice(0, counts.length); + chart.update(); + counts.splice(0, counts.length); + chart.options.plugins.annotation.annotations = annotations.slice(2); + chart.update(); + expect(counts).toEqual([2, 3, 4]); + }); + + }); }); diff --git a/types/events.d.ts b/types/events.d.ts index 5dfb63fe1..996d29664 100644 --- a/types/events.d.ts +++ b/types/events.d.ts @@ -4,6 +4,7 @@ import { AnnotationElement } from './element'; export interface EventContext { chart: Chart, element: AnnotationElement, + elements: AnnotationElement[], id: string, type: string } @@ -15,6 +16,7 @@ export interface EventContext { export interface PartialEventContext { chart: Chart, element?: Partial, + elements?: AnnotationElement[], id?: string, type?: string }