mirror of https://github.com/abpframework/abp
Merge pull request #10082 from abpframework/feat/7472
Angular UI: Move ChartComponent to @abp/ng.components/chart.jspull/10088/head
commit
889d266961
@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../../dist/packages/components/chart.js",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
|
||||
let Chart: any;
|
||||
|
||||
@Component({
|
||||
selector: 'abp-chart',
|
||||
template: `
|
||||
<div
|
||||
style="position:relative"
|
||||
[style.width]="responsive && !width ? null : width"
|
||||
[style.height]="responsive && !height ? null : height"
|
||||
>
|
||||
<canvas
|
||||
#canvas
|
||||
[attr.width]="responsive && !width ? null : width"
|
||||
[attr.height]="responsive && !height ? null : height"
|
||||
(click)="onCanvasClick($event)"
|
||||
></canvas>
|
||||
</div>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
exportAs: 'abpChart',
|
||||
})
|
||||
export class ChartComponent implements AfterViewInit, OnDestroy, OnChanges {
|
||||
@Input() type: string;
|
||||
|
||||
@Input() data: any = {};
|
||||
|
||||
@Input() options: any = {};
|
||||
|
||||
@Input() plugins: any[] = [];
|
||||
|
||||
@Input() width: string;
|
||||
|
||||
@Input() height: string;
|
||||
|
||||
@Input() responsive = true;
|
||||
|
||||
@Output() dataSelect = new EventEmitter();
|
||||
|
||||
@Output() initialized = new EventEmitter<boolean>();
|
||||
|
||||
@ViewChild('canvas') canvas: ElementRef<HTMLCanvasElement>;
|
||||
|
||||
chart: any;
|
||||
|
||||
constructor(public el: ElementRef, private cdr: ChangeDetectorRef) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
import('chart.js/auto').then(module => {
|
||||
Chart = module.default;
|
||||
this.initChart();
|
||||
this.initialized.emit(true);
|
||||
});
|
||||
}
|
||||
|
||||
onCanvasClick(event) {
|
||||
if (this.chart) {
|
||||
const element = this.chart.getElementsAtEventForMode(
|
||||
event,
|
||||
'nearest',
|
||||
{ intersect: true },
|
||||
false,
|
||||
);
|
||||
const dataset = this.chart.getElementsAtEventForMode(
|
||||
event,
|
||||
'dataset',
|
||||
{ intersect: true },
|
||||
false,
|
||||
);
|
||||
|
||||
if (element && element[0] && dataset) {
|
||||
this.dataSelect.emit({ originalEvent: event, element: element[0], dataset: dataset });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initChart = () => {
|
||||
const opts = this.options || {};
|
||||
opts.responsive = this.responsive;
|
||||
|
||||
// allows chart to resize in responsive mode
|
||||
if (opts.responsive && (this.height || this.width)) {
|
||||
opts.maintainAspectRatio = false;
|
||||
}
|
||||
|
||||
this.chart = new Chart(this.canvas.nativeElement, {
|
||||
type: this.type as any,
|
||||
data: this.data,
|
||||
options: this.options,
|
||||
});
|
||||
};
|
||||
|
||||
getCanvas = () => {
|
||||
return this.canvas.nativeElement;
|
||||
};
|
||||
|
||||
getBase64Image = () => {
|
||||
return this.chart.toBase64Image();
|
||||
};
|
||||
|
||||
generateLegend = () => {
|
||||
if (this.chart) {
|
||||
return this.chart.generateLegend();
|
||||
}
|
||||
};
|
||||
|
||||
refresh = () => {
|
||||
if (this.chart) {
|
||||
this.chart.update();
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
};
|
||||
|
||||
reinit = () => {
|
||||
if (!this.chart) return;
|
||||
this.chart.destroy();
|
||||
this.initChart();
|
||||
};
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.chart) {
|
||||
this.chart.destroy();
|
||||
this.chart = null;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (!this.chart) return;
|
||||
|
||||
if (changes.data?.currentValue || changes.options?.currentValue) {
|
||||
this.chart.destroy();
|
||||
this.initChart();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ChartComponent } from './chart.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
exports: [ChartComponent],
|
||||
declarations: [ChartComponent],
|
||||
providers: [],
|
||||
})
|
||||
export class ChartModule {}
|
@ -0,0 +1,4 @@
|
||||
export * from './chart.component';
|
||||
export * from './chart.module';
|
||||
export * from './widget-utils';
|
||||
|
@ -1 +1,3 @@
|
||||
import 'jest-canvas-mock';
|
||||
import 'jest-preset-angular/setup-jest';
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
<div
|
||||
style="position:relative"
|
||||
[style.width]="responsive && !width ? null : width"
|
||||
[style.height]="responsive && !height ? null : height"
|
||||
>
|
||||
<canvas
|
||||
[attr.width]="responsive && !width ? null : width"
|
||||
[attr.height]="responsive && !height ? null : height"
|
||||
(click)="onCanvasClick($event)"
|
||||
></canvas>
|
||||
</div>
|
@ -1,141 +0,0 @@
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnDestroy,
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { chartJsLoaded$ } from '../../utils/widget-utils';
|
||||
declare const Chart: any;
|
||||
|
||||
@Component({
|
||||
selector: 'abp-chart',
|
||||
templateUrl: './chart.component.html',
|
||||
})
|
||||
export class ChartComponent implements AfterViewInit, OnDestroy {
|
||||
@Input() type: string;
|
||||
|
||||
@Input() options: any = {};
|
||||
|
||||
@Input() plugins: any[] = [];
|
||||
|
||||
@Input() width: string;
|
||||
|
||||
@Input() height: string;
|
||||
|
||||
@Input() responsive = true;
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
|
||||
@Output() readonly onDataSelect: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@Output() readonly initialized = new BehaviorSubject(this);
|
||||
|
||||
private _initialized: boolean;
|
||||
|
||||
_data: any;
|
||||
|
||||
chart: any;
|
||||
|
||||
constructor(public el: ElementRef, private cdRef: ChangeDetectorRef) {}
|
||||
|
||||
@Input() get data(): any {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
set data(val: any) {
|
||||
this._data = val;
|
||||
this.reinit();
|
||||
}
|
||||
|
||||
get canvas() {
|
||||
return this.el.nativeElement.children[0].children[0];
|
||||
}
|
||||
|
||||
get base64Image() {
|
||||
return this.chart.toBase64Image();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
chartJsLoaded$.subscribe(() => {
|
||||
this.testChartJs();
|
||||
|
||||
this.initChart();
|
||||
this._initialized = true;
|
||||
});
|
||||
}
|
||||
|
||||
testChartJs() {
|
||||
try {
|
||||
Chart;
|
||||
} catch (error) {
|
||||
throw new Error(`Chart is not found. Import the Chart from app.module like shown below:
|
||||
import('chart.js');
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
onCanvasClick = event => {
|
||||
if (this.chart) {
|
||||
const element = this.chart.getElementAtEvent(event);
|
||||
const dataset = this.chart.getDatasetAtEvent(event);
|
||||
if (element && element.length && dataset) {
|
||||
this.onDataSelect.emit({
|
||||
originalEvent: event,
|
||||
element: element[0],
|
||||
dataset,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
initChart = () => {
|
||||
const opts = this.options || {};
|
||||
opts.responsive = this.responsive;
|
||||
|
||||
// allows chart to resize in responsive mode
|
||||
if (opts.responsive && (this.height || this.width)) {
|
||||
opts.maintainAspectRatio = false;
|
||||
}
|
||||
|
||||
this.chart = new Chart(this.canvas, {
|
||||
type: this.type,
|
||||
data: this.data,
|
||||
options: this.options,
|
||||
plugins: this.plugins,
|
||||
});
|
||||
|
||||
this.cdRef.detectChanges();
|
||||
};
|
||||
|
||||
generateLegend = () => {
|
||||
if (this.chart) {
|
||||
return this.chart.generateLegend();
|
||||
}
|
||||
};
|
||||
|
||||
refresh = () => {
|
||||
if (this.chart) {
|
||||
this.chart.update();
|
||||
this.cdRef.detectChanges();
|
||||
}
|
||||
};
|
||||
|
||||
reinit = () => {
|
||||
if (this.chart) {
|
||||
this.chart.destroy();
|
||||
this.initChart();
|
||||
}
|
||||
};
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.chart) {
|
||||
this.chart.destroy();
|
||||
this._initialized = false;
|
||||
this.chart = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
import 'jest-canvas-mock';
|
||||
import 'jest-preset-angular/setup-jest';
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue