Why are there connections between these points in chartjs? - html

I have an angular apllication I which I display a chart. The chart is filled with data from a database. The y axis displays sensordata and the x axis displays a timestamp. The timestamp is also a column in the database. When I start the app there are connections between some points that I don´t want and that don´t make sense! Why is that so?
ngOnInit(): void {
var chartOptions = {
plugins: {
legend: {
display: false
}
},
responsive: true,
maintainAspectRatio: false,
animation: {duration: 0}
};
var tempChart = new Chart('tempChart', {
type: 'line',
data: {
labels: [],
datasets: [{
data: [0],
borderWidth: 1
}]
},
options: chartOptions
});
setInterval(() => {
// API request
this.service.getMesswerte().subscribe({
next: data => {
this.chartData = data;
this.fillChartData(this.chartData);
}
})
}, 1000)
setInterval(() => {
tempChart.data.datasets[0].data = this.tempArray;
tempChart.update();
}, 1000)
}
private fillChartData(chartData: Object)
{
this.objects = Object.values(chartData);
for(let row in this.objects)
{
this.tempObject = {
x: this.objects[row].timestamp,
y: this.objects[row].airtemp
}
this.tempArray.push(this.tempObject);
}
}

Related

Update echart on data change

i'm looking for a solution to update an echart when new data comes in. Currently i have a chart and a drop down with some data.When i open the page, data is displaying at the chart perfectly fine. But when i use the drop down and change option to next data, nothing is happening. The previous data is still on the chart. Any ideas how to update the chart (object) when data changes ?
My code:
chart1: EChartOption = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['Tests Open','Tests Approved', 'Tests Failed']
},
toolbox: {
show: true,
feature: {
mark: { show: true },
magicType: { title: '1', show: true, type: ['line', 'bar',] },
restore: { title: 'Restore', show: true },
saveAsImage: { title: 'Save Chart',show: true }
}
},
xAxis: [
{
type: 'category',
axisTick: { show: false },
data: []
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: 'Tests Open',
type: 'bar',
data: [],
itemStyle: {
color: '#FDD051'
}
},
{
name: 'Tests Approved',
type: 'bar',
data: [],
itemStyle: {
color: '#2EAD6D'
}
},
{
name: 'Tests Failed',
type: 'bar',
data: [],
itemStyle: {
color:'#F0533F'
}
},
]
};
refreshChart(statistics: TestResultSiteStatistics) : void {
let months = [];
let open = [];
let approved = [];
let failed = [];
for (let month in statistics.monthly){
months.push(month);
approved.push(statistics.monthly[month].approved);
open.push(statistics.monthly[month].open);
failed.push(statistics.monthly[month].failed);
}
this.chart1.xAxis[0].data = months;
this.chart1.series[0].data = open;
this.chart1.series[1].data = failed;
this.chart1.series[2].data = approved;
}
<div #chart style="height:590px; width:1190px;" echarts [options]="chart1" ></div>
You cannot add data directly to instance because Echarts incapsulated diffucult logic to process data. You need to use method myChart.setOption({series: [new_data]}). It explained in API docs: https://echarts.apache.org/en/api.html#echartsInstance.setOption and https://echarts.apache.org/en/tutorial.html#Loading%20and%20Updating%20of%20Asynchronous%20Data

Problem in binding the data to the kendo multi-select dropdown

I have a kendo grid in angular, which is supposed to have some columns with multi-select dropdown.
When I select the item from the list for the first time, that item gets binded and the second item when selected the gridParams holds the second item selected, but once the API call returns the data, the list binded refreshes to none(no data binded to the dropdownlist).
Below is the code related
{
OC.setReportGridColumns(responsecolumns);
OC.reportsGridOptions = {
dataSource: {
schema: {
data: "Data",
total: "Total",
model: {
fields: OC.GetSchemaFields()
}
},
transport: {
read: function (e) {
gridParams = JSON.parse(JSON.stringify({
CurrentPage: e.data.page,
PageSize: e.data.pageSize,
Sort: e.data.sort,
Filter: e.data.filter
}));
if (gridParams.Filter != undefined) {
var a;
if (gridParams.Filter.filters!= undefined) {
angular.forEach(gridParams.Filter.filters, function (value, key) {
if (value.field === "QuoteStatus") {
value.operator = "in";
a = "'" + value.value + "'";
a = a.replace(",", "','");
value.value = a;
}
});
};
};
ReportService.GetAllAdHocReport(gridParams, '', OC.CustomColumnSelected, TemplateId).then(function (response) {
if (response != '') {
$("li [ui- sref='AdHocReport']").parent().addClass("activelist");
response.Total = response.Data != null && response.Data.length > 0 ? response.Data[0].TotalRecords : 10;
OC.GridConfigDataSource.read();
e.success(response);
OC.hideFilters();
} else {
e.success([]);
}
});
},
},
filterable: {
mode: "row,menu",
extra:false
},
selectable: 'cell',
columns: OC.gridCols,
}
}
}
OC.setReportGridColumns = function (colList) {
var col = JSON.parse(colList).columns;
OC.setfilterDropdown(col);
var cols = col.map(function (value) {
if (value.column == "QuoteStatus") {
return {
field: value.column,
title: value.title,
filterable: OC.filterDropdowns(value.column),
width: value.width,
sortable: true,
};
}
});
}
OC.filterDropdowns = function (column) {
return {
extra: false,
mode: "menu",
multi: true,
cell: {
showOperators: false,
template: function (args) {
/////------****Multi-select Dropdown****------///////
args.element.kendoMultiSelect({
autoBind: true,
dataTextField: "text",
dataValueField: "value",
dataSource: new kendo.data.DataSource({
data: OC.getDataForFilterDropdown(column)
}),
index: 0,
optionLabel: {
text: "--Select--",
value: ""
},
valuePrimitive: true,
});
},
}
}
}

aurelia bridge kendo grid refresh

I'm trying to use Aurelia KendoUi Bridge in my application.
In my code I have a service which returns a new KendoDataSource :
export class KendoDataSource {
ToKendoDataSource(data: any, recordCount: number, pageSize: number, currentPage: number): any {
return {
transport: {
read: (p) => {
p.success({ data: data, recordCount: recordCount });
}
},
pageSize: pageSize,
serverPaging: true,
serverFiltering: true,
serverSorting: true,
schema: {
data: (result) => {
console.log('Transforming data to kendo datasource.');
return result.data;
},
total: (result) => {
return result.recordCount;
}
}
};
}
}
And this is my viewModel:
#inject(HttpService, KendoDataSource, EventAggregator)
export class GroupList {
grid: any;
gridVM: any;
datasource: any;
pageable: any;
subscriber: any;
paginationDetailsRequest: PaginationDetailsRequest;
test: string;
constructor(private httpService: HttpService, private kendoDataSource: KendoDataSource, private eventAggregator: EventAggregator) {
this.httpService = httpService;
this.kendoDataSource = kendoDataSource;
this.eventAggregator = eventAggregator;
this.paginationDetailsRequest = new PaginationDetailsRequest(4, 1);
this.GetGroups(this.paginationDetailsRequest);
this.datasource = {
transport: {
read: {
url: 'PersonGroup/GetGroups',
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json'
},
parameterMap: function (data, type) {
if (type == "read") {
let paginationDetails = new PaginationDetailsRequest(data.pageSize, data.page);
if(data.sort && data.sort.length > 0){
paginationDetails.orderBy = data.sort[0].field;
paginationDetails.OrderDesc = (data.sort[0].dir == 'desc');
}
console.log(this.datasource);
return JSON.stringify(paginationDetails);
}
}
},
schema: {
data: "data.currentPageData",
total: "data.totalCount"
},
pageSize: 2,
serverPaging: true,
serverFiltering: true,
serverSorting: true
};
};
attached() {
this.subscriber = this.eventAggregator.subscribe('Search', response => {
this.search(response);
});
}
activate() {
this.pageable = {
refresh: true,
pageSizes: true,
buttonCount: 10
};
}
GetGroups(paginationDetails: PaginationDetailsRequest): void {
this.httpService.post('PersonGroup/GetGroups', paginationDetails)
.then(response => response.json())
.then(groups => {
console.log(groups);
if (groups.succeeded) {
this.datasource = this.kendoDataSource.ToKendoDataSource(groups.data.currentPageData, groups.totalCount, groups.pageSize, groups.currentPage);
this.grid.setDataSource(this.datasource); // initialize the grid
}
else {
//TODO: Show error messages on screen
console.log(groups.errors);
}
})
.catch(error => {
//TODO: Show error message on screen.
console.log(error);
});
}
search(searchDetails: Filter) {
console.log(searchDetails);
this.paginationDetailsRequest.filters.push(searchDetails);
console.log(this.paginationDetailsRequest);
this.GetGroups(this.paginationDetailsRequest);
}
detached() {
this.subscriber.dispose();
}
}
I understand that kendo does not have two-way data binding, But I'm trying to find a way to refresh the grid when I filter the data and the data source has changed.
Thanks.
I had this problem and found the solution by creating a new dataSource and assigning it to setDataSource, as follows... Note, getClients() is a search activated by a button click.
Here is the grid:
<ak-grid k-data-source.bind="datasource"
k-pageable.bind="{ input: true, numeric: false}"
k-filterable.bind="true"
k-sortable.bind="true"
k-scrollable.bind="true"
k-widget.bind="clientgrid"
k-selectable.bind="true">
<ak-col k-title="First Name" k-field="firstName" k-width="120px"></ak-col>
<ak-col k-title="Last Name" k-field="lastName" k-width="120px"></ak-col>
<ak-col k-title="Email Address" k-field="primaryEmail" k-width="230px"></ak-col>
</ak-grid>
And here is the code that updates the dataSource
public getClients()
{
console.log("ClientService.getClients");
this.clientService.getClients()
.then(result =>
{
this.clientList = result;
// the new datasource in the next line is displayed
// after the call to setDataSource(ds) below.
let ds: kendo.data.DataSource = new kendo.data.DataSource({
data: this.clientList,
schema: {
model: {
id: "id",
fields: {
firstName: { type: 'string' },
id: { type: 'number' },
lastName: { type: 'string' },
primaryEmail: { type: 'string' }
}
}
},
pageSize: 10
});
this.clientgrid.setDataSource(ds);
this.clientgrid.refresh();
})
.catch(err => console.log("Error returned from getClients " + err));
}
You don't really need to create a brand new datasource. To refresh the grid after changing the underlying data you can just replace the data element in the dataSource like so:
this.clientgrid.dataSource.data(this.datasource.data);

Get current day values from database to plot on highcharts

Hello i am designing a webserver which shows me a power consumption graph from a mysql database. I am a beginner and have written a code with some help that uses ajax calls to fetch the data from the database and plot it on the highcharts. Problem is that I get all the historic values saved in my database but I want only the values of current day to be plotted on the chart. This is my js code:
Highcharts.setOptions({
global: {
useUTC: false
}
});
$('#container').highcharts({
chart: {
type: 'area',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
tickPixelInterval: 100
},
yAxis: {
title: {
text: 'POWER'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' +
Highcharts.dateFormat('%d-%m-%Y %H:%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y);
}
},
legend: {
enabled: true
},
exporting: {
enabled: false
},
series: [{
name: 'Power Consumption',
data: (function () {
var data = [], i, t, d;
var request = {};
request['EndPoint'] = "arduino/charts/analog/fetch";
$.ajax({
type: "POST",
url: "../Server/fyp-processor.php",
data: JSON.stringify(request),
dataType: "json",
async: false,
success: function (result) {
if(result.Code == "1008" && (result.Data != null || result.Data != undefined)) {
for(i = 0; i < result.Data.Historic.length; i++) {
t = result.Data.Historic[i].DateTime.split(/[- :]/);
d = new Date(t[0], t[1]-1, t[2], t[3], t[4], t[5]);
data.push({
x: d,
y: parseInt(result.Data.Historic[i].Value)
});
}
}
}
});
return data;
}())
}]
});
It calls a fyp-processor php script that contains this code:
else if($postData['EndPoint'] == 'arduino/charts/analog/fetch') {
#result set
$resultSet = null;
#get all historic analog chart data
$results = $db->charts();
if(count($results) > 0) {
foreach($results as $result) {
$resultSet['Historic'][] = $result;
}
}
I would be glad if anyone could help me out to get only current DAY's data and also what changes I can do to it then to get current month and current week's data too.

Highcharts bargraph from json data in angularJS

I have a highcharts bargraph whose values are received from json whose format is as follows:
"bargraph":
[
{
"categories": "['S', 'M', 'T', 'W', 'T', 'F']",
"series1": "[800, 1100, 80, 1800, 1600, 2000]",
"series2": "[800, 1100, 80, 1800, 1200, 800]"
}
]
How can i embed those values for my bargraph in angularJS
HTML Code:
<div id="bargraph" bargraph={{bargraph}}><\div>
Directive:
angular.module('example').directive('bargraph', function () {
element.highcharts({
xAxis: [
{
categories: [] //embed categories value here
},
series: [
{
name: 'series1',
data: [] //Embed series1 data here
},
{
name: 'series2',
data: [] //Embed series2 data here
}
]
})
})
Please provide a suitable way to embed the data from json.
Here is a directive i copied and pasted from my webapp it is how i render highcharts using a directive NOTE: not all of this directive is applicable to you and some of it is specific to what i needed but you get the idea.
lrApp.directive('chart', function () {
return {
restrict: 'E',
template: '<div></div>',
transclude: true,
replace: true,
link: function (scope, element, attrs) {
var chart = null;
var chartsDefaults = {
chart: {
renderTo: element[0],
type: attrs.type || null,
height: attrs.height || null,
width: attrs.width || null,
},
colors: scope.$eval(attrs.colors) || null,
title: {
style: {
display: 'none'
}
},
xAxis: {
//categories: ['{"-7 days"|date_format}','{"-6 days"|date_format}','{"-5 days"|date_format}','{"-4 days"|date_format}', '{"-3 days"|date_format}', '{"-2 days"|date_format}', '{"-1 day"|date_format}', '{$smarty.now|date_format}'],
categories: scope.$eval(attrs.dates) || null,
gridLineDashStyle: 'ShortDot',
gridLineColor: "#C0C0C0",
gridLineWidth: 1,
labels: {
y: 27
}
},
yAxis: {
title: {
text: null
},
min: 0,
gridLineDashStyle: 'ShortDot',
gridLineColor: "#C0C0C0",
gridLineWidth: 1
},
credits: {
enabled: false
},
legend: {
enabled: false
},
plotOptions: {
series: {
shadow: false,
lineWidth: 3
}
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' +
this.x + ': ' + this.y + '</b>';
}
}
};
//Update when charts data changes
scope.$watch(attrs.value, function (newVal, oldVal) {
if (!newVal.length) return;
// We need deep copy in order to NOT override original chart object.
// This allows us to override chart data member and still the keep
// our original renderTo will be the same
var deepCopy = true;
var newSettings = {};
chartsDefaults.series = newVal;
chartsDefaults.colors = scope.$eval(attrs.colors);
chartsDefaults.xAxis.categories = scope.$eval(attrs.dates);
console.log(chartsDefaults);
chart = new Highcharts.Chart(chartsDefaults);
});
}
}
});
and this is how it used it obviously you would change "line" to bar:
<chart value="stats.sets" dates="stats.days" colors="stats.colors" type="line"></chart>