first implementation of x-chart component ...
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
import {
|
||||
Component,
|
||||
ViewChild,
|
||||
ElementRef,
|
||||
ChangeDetectionStrategy,
|
||||
} from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { isNullOrUndefined, nameof } from 'x-framework-core';
|
||||
import ApexCharts, { ApexAxisChartSeries, ApexOptions } from 'apexcharts';
|
||||
import { XChartAction, XChartContainerComponent } from './x-chart.typings';
|
||||
|
||||
@Component({
|
||||
selector: 'x-chart',
|
||||
templateUrl: './x-chart.component.html',
|
||||
styleUrls: ['./x-chart.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class XChartComponent extends XChartContainerComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
//
|
||||
@ViewChild('chartContainer', { static: true })
|
||||
chartContainer!: ElementRef;
|
||||
|
||||
//
|
||||
private chartInstance: ApexCharts | null = null;
|
||||
|
||||
//
|
||||
private ACTION_PROVIDER_SUBSCRIPTION: Subscription;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
afterViewInit() {
|
||||
super.afterViewInit();
|
||||
|
||||
//
|
||||
this.initializeComponent();
|
||||
}
|
||||
|
||||
async onChange(changeKeys: string[]) {
|
||||
super.onChange(changeKeys);
|
||||
|
||||
//
|
||||
// Auto Update ...
|
||||
const isAutoUpdateChanged = changeKeys.includes(
|
||||
nameof<XChartComponent>('autoUpdate'),
|
||||
);
|
||||
if (isAutoUpdateChanged) {
|
||||
//
|
||||
if (isNullOrUndefined(this.autoUpdate)) {
|
||||
this.autoUpdate = this.propertyProvider.autoUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check Auto Update ...
|
||||
var autoUpdate = await this.getValueAsync(this.autoUpdate);
|
||||
if (!autoUpdate || isNullOrUndefined(this.chartInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Options Changed ...
|
||||
const isOptionsChanged = changeKeys.includes(
|
||||
nameof<XChartComponent>('options'),
|
||||
);
|
||||
if (isOptionsChanged) {
|
||||
//
|
||||
if (isNullOrUndefined(this.options)) {
|
||||
this.options = this.propertyProvider.options;
|
||||
}
|
||||
|
||||
//
|
||||
const options = await this.getValueAsync(this.options);
|
||||
await this.chartInstance.updateOptions(options);
|
||||
}
|
||||
|
||||
//
|
||||
// Series Changed ...
|
||||
const isSeriesChanged = changeKeys.includes(
|
||||
nameof<XChartComponent>('series'),
|
||||
);
|
||||
if (isSeriesChanged) {
|
||||
//
|
||||
if (isNullOrUndefined(this.series)) {
|
||||
this.series = this.propertyProvider.series;
|
||||
}
|
||||
|
||||
//
|
||||
const series = await this.getValueAsync(this.series);
|
||||
await this.chartInstance.updateSeries(series);
|
||||
}
|
||||
|
||||
//
|
||||
// Action Provider Changed ...
|
||||
const isActionProviderChanged = changeKeys.includes(
|
||||
nameof<XChartComponent>('actionProvider'),
|
||||
);
|
||||
if (isActionProviderChanged) {
|
||||
this.registerActionProvider();
|
||||
}
|
||||
|
||||
//
|
||||
this.detectChanges();
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
//
|
||||
if (!isNullOrUndefined(this.chartInstance)) {
|
||||
//
|
||||
this.chartInstance.destroy();
|
||||
this.chartInstance = null;
|
||||
}
|
||||
|
||||
//
|
||||
this.unregisterActionProvider();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private ...
|
||||
private async initializeComponent() {
|
||||
//
|
||||
// Reading Requirement Properties ...
|
||||
const chartId = await this.getValueAsync(this.uuid);
|
||||
const series = await this.getValueAsync(this.series);
|
||||
const options = await this.getValueAsync(this.options);
|
||||
|
||||
//
|
||||
// Validate Options ...
|
||||
if (isNullOrUndefined(options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const computedStyle = getComputedStyle(document.documentElement);
|
||||
const primaryColor =
|
||||
computedStyle.getPropertyValue('--x-color-primary').trim() || '#008ffb';
|
||||
const textColor =
|
||||
computedStyle.getPropertyValue('--x-color-dark-contrast').trim() ||
|
||||
'#373d3f';
|
||||
const gridColor =
|
||||
computedStyle.getPropertyValue('--x-color-light-shade').trim() ||
|
||||
'#e0e0e0';
|
||||
const finalOptions: ApexOptions = {
|
||||
...options,
|
||||
series: series as any,
|
||||
chart: {
|
||||
...options.chart,
|
||||
id: chartId,
|
||||
type: options.chart?.type || 'line',
|
||||
foreColor: textColor,
|
||||
events: {
|
||||
...options.chart?.events,
|
||||
mounted: (chartContext, config) => {
|
||||
this.chartRendered.emit();
|
||||
options.chart?.events?.mounted?.(chartContext, config);
|
||||
},
|
||||
dataPointSelection: (event, chartContext, config) => {
|
||||
this.dataPointSelected.emit({ event, chartContext, config });
|
||||
options.chart?.events?.dataPointSelection?.(
|
||||
event,
|
||||
chartContext,
|
||||
config,
|
||||
);
|
||||
},
|
||||
zoomed: (chartContext, { xaxis, yaxis }) => {
|
||||
this.zoomed.emit({ xaxis, yaxis });
|
||||
options.chart?.events?.zoomed?.(chartContext, { xaxis, yaxis });
|
||||
},
|
||||
},
|
||||
},
|
||||
theme: {
|
||||
...options.theme,
|
||||
palette: options.theme?.palette || 'palette1',
|
||||
},
|
||||
colors: options.colors || [primaryColor],
|
||||
grid: {
|
||||
...options.grid,
|
||||
borderColor: gridColor,
|
||||
},
|
||||
xaxis: {
|
||||
...options.xaxis,
|
||||
labels: {
|
||||
...options.xaxis?.labels,
|
||||
style: { colors: textColor },
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
...options.yaxis,
|
||||
labels: {
|
||||
...(options.yaxis as any).labels,
|
||||
style: { colors: textColor },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
//
|
||||
this.chartInstance = new ApexCharts(
|
||||
this.chartContainer.nativeElement,
|
||||
finalOptions,
|
||||
);
|
||||
|
||||
//
|
||||
await this.chartInstance.render();
|
||||
}
|
||||
|
||||
private registerActionProvider() {
|
||||
//
|
||||
this.unregisterActionProvider();
|
||||
|
||||
//
|
||||
if (!this.actionProvider) {
|
||||
this.actionProvider = this.propertyProvider.actionProvider;
|
||||
}
|
||||
|
||||
//
|
||||
this.ACTION_PROVIDER_SUBSCRIPTION = this.actionProvider
|
||||
.asObservable()
|
||||
.subscribe(async (model) => {
|
||||
//
|
||||
switch (model.action) {
|
||||
//
|
||||
case XChartAction.Refresh:
|
||||
this.detectChanges();
|
||||
break;
|
||||
|
||||
//
|
||||
case XChartAction.Destroy:
|
||||
this.onDestroy();
|
||||
break;
|
||||
|
||||
//
|
||||
case XChartAction.UpdateSeries:
|
||||
//
|
||||
if (
|
||||
!isNullOrUndefined(model.payload) ||
|
||||
!isNullOrUndefined(this.chartInstance)
|
||||
) {
|
||||
//
|
||||
this.series = await this.getValueAsync(
|
||||
model.payload as ApexAxisChartSeries,
|
||||
);
|
||||
await this.chartInstance.updateSeries(this.series);
|
||||
this.detectChanges();
|
||||
}
|
||||
break;
|
||||
|
||||
//
|
||||
case XChartAction.UpdateOptions:
|
||||
//
|
||||
if (
|
||||
!isNullOrUndefined(model.payload) ||
|
||||
!isNullOrUndefined(this.chartInstance)
|
||||
) {
|
||||
//
|
||||
this.options = await this.getValueAsync(
|
||||
model.payload as ApexOptions,
|
||||
);
|
||||
await this.chartInstance.updateOptions(this.options);
|
||||
this.detectChanges();
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private unregisterActionProvider() {
|
||||
//
|
||||
if (!this.ACTION_PROVIDER_SUBSCRIPTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
this.ACTION_PROVIDER_SUBSCRIPTION.unsubscribe();
|
||||
this.ACTION_PROVIDER_SUBSCRIPTION = null;
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user