Сообщение о предупреждении консоли < /p>
Я попытался использовать метод, распорядившийся в автономных компонентах, но при перемещении на другую страницу и вернемся к нему, сообщение появляется в консоли, подобно предыдущему экземпляру, но при перемещении на другую страницу и вернемся к нему, сообщение появляется в консоли, подобно предыдущему экземпляру. Здесь код компонента echart: < /p>
Код: Выделить всё
import { Component, ElementRef, Input, OnChanges, SimpleChanges, AfterViewInit, OnInit, Output, EventEmitter } from '@angular/core';
import { EChartsOption } from 'echarts';
import { NgxEchartsModule } from 'ngx-echarts';
import * as echarts from 'echarts';
import { NgxEchartsDirective, provideEcharts } from 'ngx-echarts';
import { ColorService } from '../../services/color.service';
import { CommonModule } from '@angular/common';
import { Series } from '../../services/models/lineChartTimeSeriesDTO';
@Component({
selector: 'app-line-chart',
standalone: true,
imports: [
NgxEchartsDirective,
NgxEchartsModule,
CommonModule
],
providers: [provideEcharts()],
templateUrl: './line-chart.component.html',
styleUrl: './line-chart.component.css'
})
export class LineChartComponent implements OnChanges, AfterViewInit, OnInit {
@Output() chartReady = new EventEmitter();
@Input() data: Series[] = [{
name: 'default',
type: 'line',
data: [],
smooth: false,
showSymbol: false,
emphasis: {
disabled: true
}
}];
@Input() labels: string[] = [];
@Input() title: string = "";
@Input() unit: string = "";
@Input() seriesName: string = "";
@Input() legendData: string[] = [];
@Input() chartHeight: number = 400;
@Input() headerTitle: string = "";
@Input() multiplicativeFactor: number = 1;
@Input() rotateLabelXAxis: number = 0;
@Input() showSeconds: boolean = false;
chartOptions: EChartsOption = {};
chartInstance: any = null;
constructor(private el: ElementRef, private colorService: ColorService) {
this.chartOptions = this.getChartOptions();
}
ngOnInit(): void {
}
ngAfterViewInit() {
const container = this.el.nativeElement.querySelector('.chart-container-line');
if (!container) {
return;
}
const existingInstance = echarts.getInstanceByDom(container);
if (existingInstance && this.chartInstance != null) {
existingInstance.dispose();
}
container.removeAttribute('_echarts_instance_');
container.style.height = `${this.chartHeight}px`;
container.style.width = '100%';
requestAnimationFrame(() => {
this.initChart(container);
this.chartReady.emit(this.chartInstance);
});
}
private initChart(container: HTMLElement) {
// Check again if an instance already exists
const existingInstance = echarts.getInstanceByDom(container);
if (existingInstance && this.chartInstance != null) {
existingInstance.dispose();
}
// MANUALLY REMOVE ANY EXISTING REFERENCES
container.removeAttribute('_echarts_instance_');
this.chartInstance = echarts.init(container);
this.chartInstance.setOption(this.chartOptions);
this.chartInstance.on('brushEnd', (params: any) => this.onChartInit(params));
/*
setTimeout(() => {
this.chartReady = true;
}, 500);
*/
// Resize chart on window resize event
window.addEventListener('resize', () => {
if (this.chartInstance) {
this.chartInstance.resize();
}
});
}
ngOnChanges(changes: SimpleChanges): void {
/* refresh chart on data change */
if (changes['title'] || changes['unit'] || changes['data']) {
this.updateChart();
}
}
onChartInit(params: any) {
/* brush events */
if (params.areas && params.areas.length > 0) {
const selectedArea = params.areas[0];
const coordRange = selectedArea.coordRange;
if (coordRange) {
const [start, end] = coordRange;
/* Update x interval */
this.updateXAxisRange(start, end);
/* Remove selection */
this.chartInstance.dispatchAction({
type: 'brush',
areas: []
});
}
}
}
private updateXAxisRange(start: number, end: number) {
/* edit the visible range on x axis */
this.chartInstance.setOption({
xAxis: {
min: start,
max: end
}
});
}
private getChartOptions(): EChartsOption {
const maxValue = this.findFullScale(this.data);
return {
animation: false,
title: {
text: this.title,
left: "center",
textStyle: {
color: this.colorService.getColorFromCSSVariable("--whiteStandard")
},
},
legend: {
data: this.legendData,
type: 'scroll',
textStyle: {
color: this.colorService.getColorFromCSSVariable("--whiteStandard")
},
pageIconColor: this.colorService.getColorFromCSSVariable("--whiteStandard"),
pageIconInactiveColor: this.colorService.getColorFromCSSVariable("--lightGrey"),
pageTextStyle: {
color: this.colorService.getColorFromCSSVariable("--whiteStandard")
}
},
tooltip: {
show: true,
trigger: 'axis',
formatter: (params: any) => {
const timestamp = this.formatDate(params[0].axisValueLabel, this.showSeconds)
let dataValues = params.map((item: any) => {
return `${item.marker} ${item.seriesName} [b]${this.formatValue(item.value[1], maxValue, this.multiplicativeFactor)} ${this.measureUnitFormatter(maxValue, this.unit)}[/b]`
}).join('
');
return `${timestamp}
${dataValues}`;
}
},
backgroundColor: this.colorService.getColorFromCSSVariable("--darkThemeCardAlfagreen"),
toolbox: {
right: 10,
top: 25,
feature: {
restore: {},
brush: {
type: ['lineX']
}
},
iconStyle: {
borderColor: this.colorService.getColorFromCSSVariable("--whiteStandard")
}
},
grid: {
/* avoid axis label from cut */
containLabel: true,
/* auto fit margins dimensions */
left: '1.5%',
right: '1%',
top: '20%',
bottom: '10%'
},
textStyle: {
color: this.colorService.getColorFromCSSVariable("--whiteStandard")
},
xAxis: [{
type: 'time',
axisLabel: {
rotate: this.rotateLabelXAxis,
hideOverlap: true,
formatter: (value) => {
return this.formatDate(value, this.showSeconds);
}
},
name: "data e ora",
nameLocation: 'middle',
nameTextStyle: {
/* space between axis and labels */
padding: 30,
fontSize: 15,
fontWeight: 'bold'
},
splitLine: {
/* add grid lines */
show: false,
lineStyle: {
color: this.colorService.getColorFromCSSVariable("--whiteStandard"),
type: 'solid'
}
}
}],
yAxis: {
type: 'value',
name: this.measureUnitFormatter(maxValue, this.unit),
nameLocation: 'end',
nameTextStyle: {
/* space between axis and labels */
padding: 5,
fontSize: 12
},
splitLine: {
show: true,
lineStyle: {
color: this.colorService.getColorFromCSSVariable("--whiteStandard"),
type: 'solid'
}
},
axisLabel: {
formatter: (value: number) => {
return this.formatValue(value, maxValue, this.multiplicativeFactor);
}
}
},
series: this.data,
brush: {
/* enable rectangle selection */
toolbox: ['lineX'],
brushMode: 'single',
xAxisIndex: 0,
throttleType: 'fixRate',
brushType: 'lineX',
removeOnClick: true,
transformable: false
} as any,
graphic: {
type: 'text',
left: 'center',
top: 'middle',
style: {
text: this.data != null && this.data.length > 0 && this.data.every(series => series.data.length === 0) ? 'No data' : '',
fontSize: 30,
fill: this.colorService.getColorFromCSSVariable("--whiteStandard")
}
}
};
}
private updateChart() {
if (this.chartInstance) {
this.chartInstance.setOption(this.getChartOptions(), { notMerge: true });
//this.chartInstance.resize();
}
}
findFullScale(data: Series[]): number {
let overallMax = -Infinity;
/* Iterate over every series */
for (const series of data) {
// Find max
const seriesMax = Math.max(...series.data.map(arr => arr[1] * this.multiplicativeFactor));
overallMax = Math.max(overallMax, seriesMax);
}
return overallMax;
}
measureUnitFormatter(maxValue: number, unitMeasure: string): string {
if (maxValue >= 1000000000) {
return 'G' + unitMeasure;
} else if (maxValue >= 1000000) {
return 'M' + unitMeasure;
} else if (maxValue >= 1000) {
return 'k' + unitMeasure;
}
return unitMeasure;
}
formatValue(value: number, maxValue: number, multiplicativeFactor: number): string {
const realValue = value * multiplicativeFactor;
if (maxValue >= 1000000000) {
return (realValue / 1000000000).toFixed(1);
} else if (maxValue >= 1000000) {
return (realValue / 1000000).toFixed(1);
/* show K to scale number on axis */
} else if (maxValue >= 1000) {
return (realValue / 1000).toFixed(1);
}
return (realValue).toString();
}
formatDate(value: any, showSeconds: boolean): string {
const date = new Date(value);
// Day
const day = String(date.getDate()).padStart(2, '0');
// Month
const month = String(date.getMonth() + 1).padStart(2, '0');
// Year
const year = date.getFullYear();
// Hour, minutes, seconds
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
if (showSeconds) {
// Formatted string with \n
return `${day}/${month}/${year}\n${hours}:${minutes}:${seconds}`;
} else {
// Formatted string with \n
return `${day}/${month}/${year}\n${hours}:${minutes}`;
}
}
ngOnDestroy() {
/* clean memory after componenst is destroied */
if (this.chartInstance) {
this.chartInstance.dispose();
this.chartInstance = null;
}
}
}< /code>
< /div>
< /div>
< /p>
и здесь код типовойписнойпинги приборной панели, где компонент называется: < /p>
import { AfterViewInit, ChangeDetectorRef, Component, OnDestroy, ViewChild } from '@angular/core';
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
import { Router, RouterModule } from '@angular/router';
import { OnInit } from '@angular/core';
import { LineChartComponent } from '../../components/line-chart/line-chart.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { CommonModule } from '@angular/common';
import { ModalComponent } from '../../components/modal/modal.component';
import { GeoMapChartComponent } from '../../components/geo-map-chart/geo-map-chart.component';
import { ContainerTemplateComponent } from '../../templates/container-template/container-template.component';
import { NumericSummaryComponent } from "../../components/numeric-summary/numeric-summary.component";
import { PlantService } from '../../services/landingBoard/plant.service';
import { PlantResponse } from '../../services/models/landingBoardDTO';
import { Series } from '../../services/models/lineChartTimeSeriesDTO';
import { LineChartService } from '../../services/charts/lineChart.service';
import { GeoPoints } from '../../services/models/geomapChartDTO';
import { GeoMapService } from '../../services/charts/geomapChart.service';
import { LoaderComponent } from '../../templates/loader/loader.component';
import { Subscription } from 'rxjs';
import { AlarmsService } from '../../services/alarms/alarms.service';
import { ToastService } from '../../services/toast.services';
@Component({
selector: 'app-landing',
standalone: true,
imports: [
RouterModule,
NgbAccordionModule,
RouterModule,
NgbModule,
CommonModule,
ModalComponent,
GeoMapChartComponent,
LineChartComponent,
ContainerTemplateComponent,
NumericSummaryComponent,
LoaderComponent,
],
templateUrl: './landing.component.html',
styleUrl: './landing.component.css'
})
export class LandingComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('myModal') myModal!: ModalComponent;
plantData: PlantResponse[] = [];
latitude: string = "";
longitude: string = "";
dailyPowerData: Series[] = [];
measureUnit: string = "";
modal_messages!: any;
legendData: string[] = [];
geoPoints: GeoPoints[] = [];
coordinatesExchange: GeoPoints[] = [];
dynamicHeight: string = '100px';
animationType: 'progress' | 'progress-dark' | 'pulse' | false = 'progress-dark';
chartLoaded: boolean = false;
plantDataSubscription: Subscription | undefined;
plantGeoPointsSubscription: Subscription | undefined;
plantDailyPowerDataSubscription: Subscription | undefined;
alarmsDataSubscription: Subscription | undefined;
totalPagesModal: number = 1;
constructor(private plantDataService: PlantService, private lineChartService: LineChartService, private geoMapService: GeoMapService, private cdRef: ChangeDetectorRef, private router: Router, private alarmsService: AlarmsService, private toastService: ToastService) { }
ngOnInit(): void {
/* Load plant data */
this.loadPlantData();
}
ngAfterViewInit() {
/* Stop loader animation after a certain time a db is unreachable */
setTimeout(() => {
this.animationType = false;
}, 1000);
}
modalOnClick(dataSource: string, clusterId: number, clusterName: string) {
this.loadAlarmsDataForModal(dataSource, clusterId, clusterName);
}
/* Load alarms data for modal from API services */
private loadAlarmsDataForModal(dataSource: string, clusterId: number, clusterName: string): void {
this.alarmsDataSubscription = this.alarmsService.getUnresolvedAlarms(dataSource, clusterId)
.subscribe({
next: (data) => {
this.modal_messages = data;
//console.log('data for modal: ' + JSON.stringify(this.modal_messages))
this.totalPagesModal = Math.ceil(this.modal_messages.payload.length / 6);
this.myModal.modalOnClick(clusterName);
},
error: (error) => {
this.modal_messages = [];
this.toastService.errorStickyToast("Errore", "Problema durante il recupero degli allarmi");
}
});
}
/* Load data methods from API services */
private loadPlantData(): void {
this.plantDataSubscription = this.plantDataService.getPlantData()
.subscribe({
next: (data) => {
this.plantData = data;
data.forEach(item => {
const payload = item?.payload;
if (payload?.numericSummary?.empty) {
this.toastService.warningAutoDismissToast('Attenzione', `Nessun dato trovato per ${payload.plant.name}. I meter probabilmente sono offline.`);
}
});
},
error: (error) => {
this.plantData = [];
this.toastService.errorStickyToast('Errore', "Code error: " + error.status + ". Message: " + error.statusText);
}
});
}
private loadGeoPointsPlantData(): void {
this.plantGeoPointsSubscription = this.plantDataService.getPlantGeoPoints()
.subscribe({
next: (data) => {
this.geoPoints = [
{
name: '',
coord: [0, 0],
dataSource: '',
description: '',
address: ''
}
];
setTimeout(() => {
this.geoPoints = [...this.geoMapService.extractPlantGeoData(data)];
}, 500);
},
error: (error) => {
this.geoPoints = [];
}
});
}
private loadDailyPowerPlantData(): void {
this.plantDailyPowerDataSubscription = this.plantDataService.getPlantChartData()
.subscribe({
next: (data) => {
this.dailyPowerData = this.lineChartService.extractLineChartSeries(data);
this.legendData = this.lineChartService.extractLineChartSeriesNames(this.dailyPowerData);
},
error: (error) => {
this.dailyPowerData = [];
this.legendData = [];
}
});
}
onChartReady(chart: echarts.ECharts) {
this.loadDailyPowerPlantData();
}
geoChartReady(chart: echarts.ECharts) {
this.loadGeoPointsPlantData();
}
ngOnDestroy(): void {
this.plantDataSubscription?.unsubscribe();
this.plantGeoPointsSubscription?.unsubscribe();
this.plantDailyPowerDataSubscription?.unsubscribe();
this.alarmsDataSubscription?.unsubscribe();
}
navigateToCompanyPlant(dataSource: string, id: number) {
this.router.navigate(['/companyPlant'], { queryParams: { dataSource: dataSource, idLevelB: id } });
}
}
[i]
[list]
[*]
[/i]
Logout [i][/i]
[/list]
[i]
Sedi impianti industriali
@for(plant of plantData; track plant.dataSource){
@if(plant != null && plant.payload != null && plant.payload.plant != null){
[/i]{{plant.payload.plant.name}}
[i][/i]
Allarmi {{plant.payload.alarmCount}}
} @else{
}
}
Как я могу это решить?
Подробнее здесь: https://stackoverflow.com/questions/796 ... le-warning
Мобильная версия