highcharts-angular
Version:
Highcharts component for Angular.
207 lines (198 loc) • 10.1 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, signal, inject, Injectable, effect, input, model, output, DestroyRef, ElementRef, PLATFORM_ID, computed, untracked, afterRenderEffect, Directive, ChangeDetectionStrategy, Component, makeEnvironmentProviders } from '@angular/core';
import { isPlatformServer } from '@angular/common';
const HIGHCHARTS_LOADER = new InjectionToken('HIGHCHARTS_LOADER');
const HIGHCHARTS_ROOT_MODULES = new InjectionToken('HIGHCHARTS_ROOT_MODULES');
const HIGHCHARTS_OPTIONS = new InjectionToken('HIGHCHARTS_OPTIONS');
const HIGHCHARTS_CONFIG = new InjectionToken('HIGHCHARTS_CONFIG');
const HIGHCHARTS_TIMEOUT = new InjectionToken('HIGHCHARTS_TIMEOUT');
class HighchartsChartService {
constructor() {
this.highcharts = signal(null);
this.loader = inject(HIGHCHARTS_LOADER);
this.globalOptions = inject(HIGHCHARTS_OPTIONS, {
optional: true,
});
this.globalModules = inject(HIGHCHARTS_ROOT_MODULES, {
optional: true,
});
}
async loadHighchartsWithModules(partialConfig) {
const highcharts = await this.loader(); // Ensure Highcharts core is loaded
await Promise.allSettled([...(this.globalModules?.() ?? []), ...(partialConfig?.modules?.() ?? [])]);
// Return the Highcharts instance
return highcharts;
}
load(partialConfig) {
this.loadHighchartsWithModules(partialConfig).then(highcharts => {
if (this.globalOptions) {
highcharts.setOptions(this.globalOptions);
}
this.highcharts.set(highcharts);
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: HighchartsChartService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: HighchartsChartService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: HighchartsChartService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
class HighchartsChartDirective {
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
keepChartUpToDate() {
effect(async () => {
// Wait for the chart to be created
this.update();
const chart = await this.chart();
if (!this.chartCreated) {
if (chart) {
this.chartCreated = true;
}
}
else {
chart?.update(this.options(), true, this.oneToOne());
}
});
}
async destroyChart() {
const chart = await this.chart();
if (chart) {
// #56
chart.destroy();
}
}
constructor() {
/**
* Type of the chart constructor.
*/
this.constructorType = input('chart');
/**
* When enabled, Updates `series`, `xAxis`, `yAxis`, and `annotations` to match new options.
* Items are added/removed as needed. Series with `id`s are matched by `id`;
* unmatched items are removed. Omitted `series` leaves existing ones unchanged.
*/
this.oneToOne = input(false);
/**
* Options for the Highcharts chart.
*/
this.options = input.required();
/**
* Whether to redraw the chart.
* Check how update works in Highcharts
* API doc here: https://api.highcharts.com/class-reference/Highcharts.Chart#update
*/
this.update = model();
this.chartInstance = output(); // #26
this.destroyRef = inject(DestroyRef);
this.el = inject(ElementRef);
this.platformId = inject(PLATFORM_ID);
this.relativeConfig = inject(HIGHCHARTS_CONFIG, {
optional: true,
});
this.timeout = inject(HIGHCHARTS_TIMEOUT, {
optional: true,
});
this.highchartsChartService = inject(HighchartsChartService);
this.chartCreated = false;
this.constructorChart = computed(() => {
const highCharts = this.highchartsChartService.highcharts();
if (highCharts) {
return highCharts[this.constructorType()];
}
return undefined;
});
// Create the chart as soon as we can
this.chart = computed(async () => {
await this.delay(this.relativeConfig?.timeout ?? this.timeout ?? 500);
return this.constructorChart()?.(this.el.nativeElement,
// Use untracked, so we don't re-create new chart everytime options change
untracked(() => this.options()),
// Use Highcharts callback to emit chart instance, so it is available as early
// as possible. So that Angular is already aware of the instance if Highcharts raise
// events during the initialization that happens before coming back to Angular
createdChart => this.chartInstance.emit(createdChart));
});
// should stop loading on the server side for SSR
if (this.platformId && isPlatformServer(this.platformId)) {
return;
}
// make sure to load global config + modules on demand
this.highchartsChartService.load(this.relativeConfig);
this.destroyRef.onDestroy(() => this.destroyChart()); // #44
afterRenderEffect(() => {
if (this.update()) {
this.update.set(false); // clear the flag after update
}
});
// Keep the chart up to date whenever options change or the update special input is set to true
this.keepChartUpToDate();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: HighchartsChartDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: HighchartsChartDirective, isStandalone: true, selector: "[highchartsChart]", inputs: { constructorType: { classPropertyName: "constructorType", publicName: "constructorType", isSignal: true, isRequired: false, transformFunction: null }, oneToOne: { classPropertyName: "oneToOne", publicName: "oneToOne", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, update: { classPropertyName: "update", publicName: "update", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { update: "updateChange", chartInstance: "chartInstance" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: HighchartsChartDirective, decorators: [{
type: Directive,
args: [{
selector: '[highchartsChart]',
}]
}], ctorParameters: () => [] });
class HighchartsChartComponent {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: HighchartsChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: HighchartsChartComponent, isStandalone: true, selector: "highcharts-chart", hostDirectives: [{ directive: HighchartsChartDirective, inputs: ["constructorType", "constructorType", "oneToOne", "oneToOne", "options", "options", "update", "update"], outputs: ["chartInstance", "chartInstance", "updateChange", "updateChange"] }], ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: HighchartsChartComponent, decorators: [{
type: Component,
args: [{
selector: 'highcharts-chart',
template: '',
hostDirectives: [
{
directive: HighchartsChartDirective,
inputs: ['constructorType', 'oneToOne', 'options', 'update'],
outputs: ['chartInstance', 'updateChange'],
},
],
changeDetection: ChangeDetectionStrategy.OnPush,
}]
}] });
const emptyModuleFactoryFunction = () => [];
const defaultInstanceFactoryFunction = () => import('highcharts/esm/highcharts').then(m => m.default);
function provideHighchartsInstance(instance) {
return makeEnvironmentProviders([
{
provide: HIGHCHARTS_LOADER,
useValue: instance ?? defaultInstanceFactoryFunction,
},
]);
}
function provideHighchartsOptions(options) {
return makeEnvironmentProviders([{ provide: HIGHCHARTS_OPTIONS, useValue: options }]);
}
function provideHighchartsRootModules(modules) {
return makeEnvironmentProviders([{ provide: HIGHCHARTS_ROOT_MODULES, useValue: modules }]);
}
function providePartialHighcharts(config) {
return { provide: HIGHCHARTS_CONFIG, useValue: config };
}
function provideHighcharts(config = {}) {
const providers = [
provideHighchartsInstance(config.instance),
provideHighchartsRootModules(config.modules ?? emptyModuleFactoryFunction),
{ provide: HIGHCHARTS_TIMEOUT, useValue: config.timeout },
];
if (config.options) {
providers.push(provideHighchartsOptions(config.options));
}
return makeEnvironmentProviders(providers);
}
/*
* Public API Surface of highcharts-angular
*/
/**
* Generated bundle index. Do not edit.
*/
export { HighchartsChartComponent, HighchartsChartDirective, provideHighcharts, providePartialHighcharts };
//# sourceMappingURL=highcharts-angular.mjs.map