Im having some random issues in Ionic 3 with charts JS, they are not dynamically updating data on select box selection, I’m having to double click the legend for it to be drawn, I’m also getting a Skip issue once hovered over or clicked. please see my markup and TS code below.
<ion-item class="select">
<ion-label class="tankName">Choose Tank</ion-label>
<ion-select #T (ionChange)="updateValues(T.value)" [(ngModel)]="Converter.tankSelect">
<ion-option *ngFor="let item of Converter.tankOptionList" value="{{item.value}}">{{item.text}}</ion-option>
</ion-select>
</ion-item>
</ion-list>
<canvas #lineCanvas class="paramsCharts" width="400" height="400" style="background-color:aliceblue"></canvas>
import { Component, ViewChild } from ‘@angular/core’;
import { NavController, NavParams, ToastController } from ‘ionic-angular’;
//import { Storage } from ‘@ionic/storage’;
//import { AlertController } from ‘ionic-angular’;
import { Chart } from ‘chart.js’;
import ‘chartjs-plugin-annotation’;
import { PopoverController } from ‘ionic-angular’;
//import { TkpAmmoniaPage } from ‘…/tkp-ammonia/tkp-ammonia’;
import { FormGroup, Validators, FormBuilder } from ‘@angular/forms’;
import { Slides } from ‘ionic-angular’;
//pages…///
import { HomePage } from ‘…/…/pages/home/home’;
import { PopoverPage } from ‘…/…/pages/popover/popover’;
import { QrScannerPage } from ‘…/…/pages/qr-scanner/qr-scanner’;
import { SettingsPage } from ‘…/…/pages/settings/settings’;
//Providers//
import { ApiProvider } from ‘…/…/providers/api/api’;
import { Measurement } from ‘…/…/models/measurement’;
import { MeasurementType } from ‘…/…/models/measurementtype’;
import { ConverterProvider } from ‘…/…/providers/converter/converter’;
import { GlobalvarsProvider } from ‘…/…/providers/globalvars/globalvars’;
import { Tank } from ‘…/…/models/tank’;
//Models…//
//import { User } from ‘…/…/models/user’;
//import { Tank } from ‘…/…/models/tank’;
@Component({
selector: ‘page-measurements’,
templateUrl: ‘wap-measurements.html’,
})
export class WapMeasurementsPage {
@ViewChild(‘lineCanvas’) lineCanvas;
@ViewChild(Slides) slides: Slides;
lineChart: any;
chartLabel: any;
statusImg: any;
statusText: any;
dateTimeNow: any;
userID: any;
tanks: Tank[];
public labelArray: string[] = [];
public dataArray: any[] = [];
public upperArray: any[] = [];
public lowerArray: any[] = [];
public desiredArray: any[] = [];
//API Measurements
add_measurement_form: FormGroup;
measurements: Measurement[];
measurementsLimited: Measurement[];
tankID: string;
typeID: string;
latestMeasurement: any;
measurementDifference: any;
measurementType: MeasurementType[];
pageTitle: string;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
//private storage: Storage,
//private alertCtrl: AlertController,
public popoverCtrl: PopoverController,
public apiProvider: ApiProvider,
public Converter: ConverterProvider,
public formBuilder: FormBuilder,
public globalVars: GlobalvarsProvider,
private toast: ToastController)
{
this.statusImg = '';
this.statusText = '';
this.chartLabel = '';
this.tankID = globalVars.getTankID();
this.typeID = globalVars.getCurrentWAPTypeID();
this.dateTimeNow = new Date()
this.dateTimeNow = this.dateTimeNow.toISOString();
this.apiProvider.getMeasurementTypeByID(this.typeID).subscribe(type => {
this.pageTitle = type[0].Name;
})
//add measurement form builder
// UPDATE THIS WITH TANK DATA MODEL
this.userID = this.globalVars.getUserID();
this.add_measurement_form = formBuilder.group({
tankID: [this.tankID.toString()],
reading: ["", Validators.required],
dateTimeTaken: [this.dateTimeNow.toString()],
typeID: [this.typeID.toString()]
});
this.apiProvider.getUserTanks(this.userID).subscribe(tank => {
this.tanks = tank;
//Tank Select Data
this.Converter.tankOptionList.length = 0;
for (var i = 0; i < this.tanks.length; i++)
{
this.Converter.tankOptionList.push ({ value: i, text: this.tanks[i].Name, checked: false });
}
})
};
updateValues(value: number){
this.tankID = this.tanks[this.Converter.tankSelect].ID;
this.globalVars.setTankID(this.tanks[this.Converter.tankSelect].ID);
this.updateChart();
}
submitValue(){
//submit value to API…
this.apiProvider.createMeasurement(this.add_measurement_form.value)
.subscribe(
measurement => {
console.log(measurement);
this.updateChart();
},
error => console.log(error)
);
}
ValueSubmitted(){
this.toast.create({
message: ‘You have submitted a value!’ ,
duration: 3000
}).present();
this.navCtrl.push(WapMeasurementsPage);
}
ionViewDidLoad() {
//Measurement API Call code…//
/*
this.storage.get('CurrentTankID').then((val) => {
this.tankID = val;
})
this.storage.get('CurrentWAPTypeID').then((val) => {
console.log(val);
currentType = val;
})
*/
// should we add a default tanbk field to db to sync when online.
this.updateChart();
}
updateChart(){
this.apiProvider.getMeasurementTypeByID(this.typeID).subscribe(measurementtype => {
this.measurementType = measurementtype;
})
this.apiProvider.getMeasurements(this.tankID, this.typeID).subscribe(measurement => {
this.measurements = measurement;
this.latestMeasurement = this.measurements[0].Reading;
this.measurementDifference = parseFloat(this.measurements[0].Reading) - parseFloat(this.measurements[1].Reading);
if (this.measurementDifference > 0){
this.measurementDifference = '+' + this.measurementDifference.toString();
}
})
this.lineChart = new Chart(this.lineCanvas.nativeElement, {
type: 'line',
data: {
labels: this.labelArray,
datasets: [
{
label: 'Actual',
data: this.dataArray,
duration: 2000,
easing: 'easeInQuart',
fill: false,
borderWidth: 2,
borderColor: '#46add4'
},
/* {
label: 'Upper',
data: [0,0,0,0,0],
duration: 2000,
easing: 'easeInQuart',
fill: false,
borderWidth: 2,
borderColor: 'red',
radius: 0,
},
{
label: 'Lower',
data: [0,0,0,0,0],
duration: 2000,
easing: 'easeInQuart',
fill: false,
borderWidth: 2,
borderColor: 'red',
radius: 0,
},
{
label: 'Desired',
data: [0,0,0,0,0],
duration: 2000,
easing: 'easeInQuart',
fill: false,
borderWidth: 2,
borderColor: 'blue',
radius: 0,
}*/
]
},
options: {
annotation: {
drawTime: 'afterDatasetsDraw',
annotations: [{
type: 'box',
id: 'upperDangerLevel',
xScaleID: 'x-axis-0',
yScaleID:'y-axis-0',
yMax:1500,
yMin:1400,
borderWidth:1,
backgroundColor:'rgba(244, 72, 66,0.7)',
onMouseenter: function(e) {},
onMouseover: function(e) {},
onMouseleave: function(e) {},
onMouseout: function(e) {},
onMousemove: function(e) {},
onMousedown: function(e) {},
onMouseup: function(e) {},
onClick: function(e) {},
onDblclick: function(e) {},
onContextmenu: function(e) {},
onWheel: function(e) {}
},{
type: 'box',
id: 'lowerDangerLevel',
xScaleID: 'x-axis-0',
yScaleID:'y-axis-0',
yMax:1100,
yMin:1000,
borderWidth:1,
backgroundColor:'rgba(244, 72, 66,0.7)',
onMouseenter: function(e) {},
onMouseover: function(e) {},
onMouseleave: function(e) {},
onMouseout: function(e) {},
onMousemove: function(e) {},
onMousedown: function(e) {},
onMouseup: function(e) {},
onClick: function(e) {},
onDblclick: function(e) {},
onContextmenu: function(e) {},
onWheel: function(e) {}
},
{
type: 'line',
id: 'desiredLevel',
mode: 'horizontal',
scaleID: 'y-axis-0',
value: 1350,
borderWidth: 2,
borderDash: [2,2],
borderColor: "green",
onMouseenter: function(e) {},
onMouseover: function(e) {},
onMouseleave: function(e) {},
onMouseout: function(e) {},
onMousemove: function(e) {},
onMousedown: function(e) {},
onMouseup: function(e) {},
onClick: function(e) {},
onDblclick: function(e) {},
onContextmenu: function(e) {},
onWheel: function(e) {}
}]
},
title:{
display: true,
text:'Level',
},
maintainAspectRatio: true,
legend: {
display: true,
labels:{
useLineStyle: true
},
fontSize: 15,
padding: 0
},
scales: {
yAxes: [{
ticks:{
beginAtZero:false,
stepSize: "auto",
display: true,
},
gridLines: {
color: 'grey',
display: false
},
scaleLabel: {
display: true,
labelString: 'Measurement Value (ppt)',
}
}],
xAxes: [{
ticks:{
display: true,
beginAtZero:true,
stepSize: "auto",
},
gridLines: {
color: 'grey',
display: false
},
scaleLabel: {
display: true,
labelString: 'Time',
}
}]
}
}
})
this.apiProvider.getMeasurementsLimited(this.tankID, this.typeID, '5').subscribe(measurementLimited => {
this.measurementsLimited = measurementLimited;
// ###### ADD ERROR HANDLING HERE ####
this.dataArray.length = 0;
this.upperArray.length = 0;
this.lowerArray.length = 0;
this.desiredArray.length = 0;
this.labelArray.length = 0;
this.dataArray.push(parseFloat(this.measurementsLimited[0].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[1].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[2].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[3].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[4].Reading));
// Pull in measurement Upper
/*
this.dataArray.push(parseFloat(this.measurementsLimited[0].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[1].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[2].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[3].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[4].Reading));
*/
// Pull in measurement Lower
/*
this.dataArray.push(parseFloat(this.measurementsLimited[0].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[1].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[2].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[3].Reading));
this.dataArray.push(parseFloat(this.measurementsLimited[4].Reading));
*/
this.upperArray.push(parseFloat(this.measurementType[0].Upper));
this.upperArray.push(parseFloat(this.measurementType[0].Upper));
this.upperArray.push(parseFloat(this.measurementType[0].Upper));
this.upperArray.push(parseFloat(this.measurementType[0].Upper));
this.upperArray.push(parseFloat(this.measurementType[0].Upper));
this.lowerArray.push(parseFloat(this.measurementType[0].Lower));
this.lowerArray.push(parseFloat(this.measurementType[0].Lower));
this.lowerArray.push(parseFloat(this.measurementType[0].Lower));
this.lowerArray.push(parseFloat(this.measurementType[0].Lower));
this.lowerArray.push(parseFloat(this.measurementType[0].Lower));
this.desiredArray.push(parseFloat(this.measurementType[0].Desired));
this.desiredArray.push(parseFloat(this.measurementType[0].Desired));
this.desiredArray.push(parseFloat(this.measurementType[0].Desired));
this.desiredArray.push(parseFloat(this.measurementType[0].Desired));
this.desiredArray.push(parseFloat(this.measurementType[0].Desired));
// if length of lower limit array = 0, rename upper limit to target, otherwise display lower and upper boundaries.
this.labelArray.push('');
this.labelArray.push('');
this.labelArray.push('');
this.labelArray.push('');
this.labelArray.push('');
if(parseFloat(this.latestMeasurement) === parseFloat(this.measurementType[0].Desired))
{
this.statusText = this.measurementType[0].OK;
this.statusImg = 'https://aquamate.pro/images/app/content/statusOK.ico';
}
else if(parseFloat(this.latestMeasurement) < parseFloat(this.measurementType[0].Upper)
&& parseFloat(this.latestMeasurement) > parseFloat(this.measurementType[0].Lower))
{
this.statusText = this.measurementType[0].Warning;
this.statusImg = 'https://aquamate.pro/images/app/content/statusWarning.ico';
}
else if(parseFloat(this.latestMeasurement) > parseFloat(this.measurementType[0].Upper)
|| parseFloat(this.latestMeasurement) < parseFloat(this.measurementType[0].Lower))
{
this.statusText = this.measurementType[0].Danger;
this.statusImg = 'https://aquamate.pro/images/app/content/statusDanger.ico';
}
this.lineChart.data.datasets[0].data = this.dataArray;
this.lineChart.data.datasets[1].data = this.upperArray;
this.lineChart.data.datasets[2].data = this.lowerArray;
this.lineChart.data.datasets[3].data = this.desiredArray;
this.lineChart.data.labels = this.labelArray;
this.lineChart.update();
})
}
//Navigation stack…///
slideToHistory(){
this.slides.slideTo(1, 500);
}
slideToStatus(){
this.slides.slideTo(0,500);
}
slideToAddVal(){
this.slides.slideTo(2,500);
}
seneyeConnected(){
this.toast.create({
message: ‘Seneye Connection Comming Soon!’ ,
duration: 3000
}).present();
}
returnHome(){
this.navCtrl.push(HomePage);
}
qrScanner(){
this.navCtrl.push(QrScannerPage);
}
showSettingsPage() {
this.navCtrl.push(SettingsPage);
}
presentPopover(myEvent) {
let popover = this.popoverCtrl.create(PopoverPage);
popover.present({
ev: myEvent
});
}
}