I created a Highchart with custom range filter. The chart data is loaded from a web service. I call this service from ngOnInit method. Like this
TS
import { Component, OnInit } from "@angular/core";
import * as Highcharts from "highcharts/highstock";
import { HttpClient } from "@angular/common/http";
import * as moment from "moment";
declare var require: any;
require("highcharts/highcharts-more")(Highcharts);
require("highcharts/modules/exporting")(Highcharts);
require("highcharts/modules/export-data")(Highcharts);
@Component({
selector: "app-root",
templateUrl: "./app.component.html"
})
export class AppComponent implements OnInit {
seriesOptions: any = [];
ranges: any;
pickerlang: any;
seriesCounter = 0;
names = ["MSFT", "AAPL"];
selected: any;
chart: any;
updateFromInput = false;
Highcharts = Highcharts;
chartConstructor = "stockChart";
chartCallback: any;
chartOptions: any;
constructor(private http: HttpClient) {
const self = this;
this.chartCallback = chart => {
self.chart = chart;
};
}
ngOnInit() {
moment.locale("es");
this.names.forEach((element, i) => {
this.http
.get(
"https://www.highcharts.com/samples/data/" +
element.toLowerCase() +
"-c.json"
)
.forEach((data: any) => {
this.seriesOptions[i] = {
name: element,
data: data
};
this.seriesCounter += 1;
if (this.seriesCounter === this.names.length) {
this.createGraph();
}
});
});
this.ranges = {
Hoy: [moment(), moment()],
Ayer: [moment().subtract(1, "days"), moment().subtract(1, "days")],
"Últimos 7 días": [moment().subtract(6, "days"), moment()],
"Últimos 30 días": [moment().subtract(29, "days"), moment()],
"Este mes": [moment().startOf("month"), moment().endOf("month")],
"Mes pasado": [
moment()
.subtract(1, "month")
.startOf("month"),
moment()
.subtract(1, "month")
.endOf("month")
]
};
this.pickerlang = {
format: "DD/MM/YYYY",
direction: "ltr",
weekLabel: "W",
cancelLabel: "Cancelar",
applyLabel: "Aceptar",
clearLabel: "",
daysOfWeek: moment.weekdaysMin(),
monthNames: moment.monthsShort(),
customRangeLabel: "Seleccionar fecha",
firstDay: 1
};
}
createGraph() {
this.chartOptions = {
lang: {
loading: "Cargando...",
months: [
"Enero",
"Febrero",
"Marzo",
"Abril",
"Mayo",
"Junio",
"Julio",
"Agosto",
"Septiembre",
"Octubre",
"Noviembre",
"Diciembre"
],
weekdays: [
"Domingo",
"Lunes",
"Martes",
"Miércoles",
"Jueves",
"Viernes",
"Sábado"
],
shortMonths: [
"Ene",
"Feb",
"Mar",
"Abr",
"May",
"Jun",
"Jul",
"Ago",
"Sep",
"Oct",
"Nov",
"Dic"
],
rangeSelectorFrom: "Desde",
rangeSelectorTo: "Hasta",
rangeSelectorZoom: "Período",
downloadPNG: "Descargar imagen PNG",
downloadJPEG: "Descargar imagen JPEG",
downloadPDF: "Descargar imagen PDF",
downloadSVG: "Descargar imagen SVG",
downloadCSV: "Descargar imagen CSV",
downloadXLS: "Descargar imagen XLS",
printChart: "Imprimir",
resetZoom: "Reiniciar zoom",
resetZoomTitle: "Reiniciar zoom",
viewData: "Ver tabla",
openInCloud: "Ver en web",
thousandsSep: ",",
decimalPoint: "."
},
xAxis: {
crosshair: {
width: 1,
color: "red"
}
},
rangeSelector: {
enabled: false
},
chart: {
zoomType: "x",
panning: true,
panKey: "shift"
},
exporting: {
enabled: true
},
plotOptions: {
series: {
showInNavigator: true
}
},
tooltip: {
pointFormat:
'<span style="color:{series.color}">{series.name}</span>: <b>{point.y} litros</b><br/>',
valueDecimals: 2,
split: true
},
series: this.seriesOptions
};
}
setExtremes() {
const self = this,
chart = self.chart;
chart.showLoading();
setTimeout(() => {
chart.hideLoading();
chart.xAxis[0].setExtremes(
new Date(
this.selected["startDate"].toJSON().substring(0, 10)
).getTime(),
new Date(this.selected["startDate"].toJSON().substring(0, 10)).getTime()
);
self.updateFromInput = true;
}, 1000);
}
}
HTML
<div class="card">
<div class="card-body">
<input type="text" ngxDaterangepickerMd [locale]="pickerlang" [(ngModel)]="selected" class="form-control"
placeholder="Rango de fecha" class="form-control" [ranges]="ranges" [showCustomRangeLabel]="true"
[alwaysShowCalendars]="true" />
<highcharts-chart id="container" [Highcharts]="Highcharts" [constructorType]="chartConstructor"
[options]="chartOptions" [callbackFunction]="chartCallback" [(update)]="updateFromInput" [oneToOne]="true">
</highcharts-chart>
<button (click)=" setExtremes()" class="btn btn-primary">Buscar </button>
</div>
</div>
Chart is trying to load data before is start ngOninit, so return in console.log
Cannot read property 'series' of undefined
Anyway all works, chart has data and filter is fine, but i want chart wait to ngOnit to show data to avoid show this error in console.
So the question is: How can i force highchart to wait to ngOnInit?
SOLUTION
Full solution code: https://github.com/ElHombreSinNombre/angular-highcharts