Data not being displayed properly through ajax call - javascript

I'm currently trying to get a chart I have as drilldown remove all series data previously and redraw with new data. Below I've added the ajax calls and the html/javascript for the chart. The problem was that everytime I called the chart, it would rebuild the chart and double call. So I've been trying to get it to simply remove the data and redraw with new data from the ajax call.
AJAX & SetData call:
self.drilldownLoad = (year: number) => {
self.isDrilldownLoading(true);
self.isDrilldownLoaded(false);
$.ajax({
xhrFields: { withCredentials: true },
url: areaUrl + "api/Incident/IncidentDrilldown?year=" + year,
success: data => {
self.isDrilldownLoading(false);
self.data(data);
self.setDrilldownPlotData(data);
self.isDrilldownLoaded(true);
},
error: data => {
self.loadingError(true)
}
});
}
self.setDrilldownPlotData = (data: any) => {
while (self.drilldownPlotData().length) {
self.drilldownPlotData().pop();
}
while (self.drilldownPlotDataLabels().length) {
self.drilldownPlotDataLabels().pop();
}
var len = data.List.length,
i;
var criticalData = [];
for (i = 0; i < len; i++) {
criticalData.push(
data.List[i].Critical
)
}
var highData = [];
for (i = 0; i < len; i++) {
highData.push(
data.List[i].High
)
}
var mediumData = [];
for (i = 0; i < len; i++) {
mediumData.push(
data.List[i].Medium
)
}
var lowData = [];
for (i = 0; i < len; i++) {
lowData.push(
data.List[i].Low
)
}
for (i = 0; i < len; i++) {
self.drilldownPlotDataLabels.push(
data.List[i].IncidentMonth
)
}
self.drilldownPlotData.push(
{
name: 'Critical',
data: criticalData,
color: '#fa5a5a',
},
{
name: 'High',
data: highData,
color: '#fea156',
},
{
name: 'Medium',
data: mediumData,
visible: false,
color: '#b191c3',
},
{
name: 'Low',
data: lowData,
visible: false,
color: '#83bfd1',
}
)
}
This creates the initial chart. Once the chart is initialized, I set it to not be recreated every time I have data load from this particular ajax call. I can't seem to get it load the series data in correctly and redraw the chart.
var = subchartCreated = false;
viewModel.isDrilldownLoaded.subscribe(function () {
if (!subchartCreated) {
specificChart();
subchartCreated = true;
}
if (subchartCreated === true)
{
for (var i = 0; i < specificChart.series.length; i++) {
specificChart.series[i].remove(true); //forces the chart to redraw
}
}
});
I have two charts, one chart is the initial chart and that one is loading just fine. The second chart is the one of interest and I would like to have it load once and then simply load the series data, remove it from the second chart and then redraw with the new data. This is the click function that I have in the first chart to load the second chart. Currently, it works on the first load, but will not update data beyond that.
point: {
events: {
click: function () {
viewModel.drilldownLoad(this.category);
$('#drilldownButton').removeClass('hidden');
$('#yearlyincident-container').addClass('hidden');
$('#drilldown-container').removeClass('hidden');
$('#incidentInfoGrid').addClass('hidden');
$('#incidentDrillDownGrid').removeClass('hidden');
getDrilldownData(this.category);
}
}
}
I feel like its a relatively easy fix, but I'm just not getting it right. My initial attempts only removed the click functionality of the first chart. Any help with this would be greatly appreciated. Thanks!

Related

error code in console after using destroy function from chart.js

let myChart = null;
function draw(){
const labels = [];
for (var i = 0; i < stats.length; i++) {
labels.push(legend[i]);
}
const data = {
labels: labels,
datasets: [{
backgroundColor: ['rgb(204,0,0)', 'rgb(241,194,50)', 'rgb(41,134,204)', 'rgb(106,168,79)', 'rgb(255,62,153)'],
data: stats,
}]
};
const config = {
type: 'doughnut',
data: data,
options: {
radius: 200,
hoverOffset: 30,
aspectRatio: 1,
maintainAspectRatio: false,
responsive: false,
}
};
if (myChart !== null) {
myChart.destroy();
}
myChart = new Chart(document.getElementById('defaultCanvas0'), config);
}
When i run this code my chart just keeps flickering and drawing itself over and over again with a new id each time. I need to be able to destroy my original chart before drawing a new one
This is what console.log displays:
Edit:
function HealthStudy() {
//name for the visualisation to appear in the menu bar
this.name = "Health study";
//each visualisation must have a unique ID with no special characters
this.id = "Health-study";
//property to represent whether stats has been loaded
this.loaded = false;
// Preload the stats. This function is called automatically by the
// gallery when a visualisation is added.
this.preload = function () {
var self = this;
this.stats = loadTable(
'./data/health/causes-of-death.csv', 'csv', 'header',
// Callback function to set the value
// this.loaded to true.
function (table) {
self.loaded = true;
});
};
this.setup = function () {
if (!this.loaded) {
console.log('stats not yet loaded');
return;
}
// Create a select DOM element.
this.select = createSelect();
this.select.position(800, 380);
// Fill the options with all country names.
var countries = this.stats.columns;
// First entry is empty.
for (let i = 1; i < countries.length; i++) {
this.select.option(countries[i]);
}
};
this.destroy = function () {
this.select.remove();
};
// Create a new donut object.
this.donut = new Donut(width / 2, height / 2, width * 0.4);
this.draw = function () {
if (!this.loaded) {
console.log('stats not yet loaded');
return;
}
// Get the value of the country we're interested in from the
// select item.
var country = this.select.value();
// Get the column of raw stats for country.
var col = this.stats.getColumn(country);
// Convert all stats strings to numbers.
col = stringsToNumbers(col);
// Copy the row labels from the table (the first item of each row).
var legend = this.stats.getColumn(0);
// Colour to use for each category.
var colours = ['#CC0000', '#55a5f2', '#4dff00', '#f4e410', '#6a329f'];
// Make a title.
var title = 'Top 5 causes of death in ' + country;
// Draw the Donut!
this.donut.draw(col, legend, colours, title);

Graph 1 hangs when function called second time

I want to generate graphs dynamically when I click on a button. My problem is when I click the button second time, the first graphs blocks displaying data.
The problem is with setInterval used within addChart function but I can't figure out how to rectify the issue. Is there some sanity in my logic or not?
<script>
function addChart() {
chartCount++;
var name = document.getElementById("chartName").value;
chartDict[name] = chartCount;
chart[chartCount] = new CanvasJS.Chart("chartContainer" + chartCount, {
title: {
text: name
},
axisY: {
includeZero: false,
maximum: 70
},
axisX: {
valueFormatString: "hh:mm tt"
},
data: [{
type: "line",
dataPoints: dps[chartCount]
}]
});
updateChart[chartCount] = function(count) {
count = count || 1;
for (var j = 0; j < count; j++) {
dps[chartCount].push({
x: xVal[chartCount],
y: yVal[chartCount]
});
xVal[chartCount] = new Date()
//console.log(xVal)
//xVal++;
}
if (dps[chartCount].length > dataLength) {
dps[chartCount].shift();
}
chart[chartCount].render();
};
intervals[chartCount] = setInterval(updateChart[chartCount], 1000)
}
</script>
You can try below workaround :
Remove the chart's inner content from DOM before reassigning the new values to chart element
Below is link to use remove() method of jquery:
https://api.jquery.com/remove/

Pie chart color not changing

I am using a canvasjs to make a pie chart. I am using it in my custom code where I am getting the response from the server in an xml file and then I am using it to fill the chart values. My problem is that I am not able to change the colour of the chart meaning even for different labels the colour remains the same for the whole pie chart.
I used debugger also where it the value for colour is changing but still I am not able to resolve it.
color: scopes.chart_color_value[i]
I am using an another configuration file where I am storing colour values.
Here is my custom code
$scope.loadChartValue = function (data, scopes) {
scopes.data_id = [];
scopes.legend_text = "";
scopes.inner_chart_data = [];
for (var i = 0; i <= data.length; i++) {
var arrayvalue = data[0].data[i]._attr
if (existsInArray(scopes.data_id, arrayvalue.label._value) == false) {
scopes.data_id.push(arrayvalue.label._value);
}
}
scopes.inner_chart_data = [];
var i=1;
for (var j = 0; j < data[0].data.length; j++) {
scopes.inner_chart_data.push({ label: data[0].data[j]._attr.label._value, y: data[0].data[j]._attr.value._value });
scopes.dataset.push(
{
type: "pie",
markerType: "circle",
markerSize: scopes.markersize,
color: scopes.chart_color_value[i],
showInLegend: false,
name: scopes.legend_text,
dataPoints: scopes.inner_chart_data
}
);
i++;
}
}
It seems you are creating 2 data-series instead of 1 data-series with 2 dataPoints. When color is set at data-series level, whole pie becomes single color, so try changing it at data-point level.
The following code should work fine.
for (var j = 0; j < data[0].data.length; j++) {
scopes.inner_chart_data.push({ label: data[0].data[j]._attr.label._value, y: data[0].data[j]._attr.value._value, color: scopes.chart_color_value[i], });
i++;
}
scopes.dataset.push(
{
type: "pie",
markerType: "circle",
markerSize: scopes.markersize,
showInLegend: false,
name: scopes.legend_text,
dataPoints: scopes.inner_chart_data
}
);

Showing Progress while Child row loads

Coming again with another question :)
This time I had a requirement to show some progress while Child rows are being loaded. Since there is an Api call which relatively takes little time to return data, I do want to show the some progress unless the user who clicks the parent row is totally unaware whether there is a call done to see its child rows.
What I have done:
I wrote a style sheet class which has a
loader-small.gif
image as this:
tr.loading td.details-control {
background: url('/Images/loader-small.gif') no-repeat center center;
}
and applied like this:
$('#accountManagerEarningsDataTable tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row(tr);
try {
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
//Calling the loading Class ------>
tr.addClass('loading');
// Open this row
var arrForTable1 = [];
var arrForTable2 = [];
totalBrokerage = 0;
totalRetailBrokerage = 0;
totalSelfServiceBrokerage = 0;
console.log('You selected: ' + row.data().AccountManagerID);
var settings = {
"columnDefs": [
{ targets: 1, align: "right", decimals: 0 },
{ targets: 2, align: "right", decimals: 0 },
{ targets: 3, align: "right", decimals: 0 },
{ targets: 4, align: "right", decimals: 2 },
{ targets: 5, align: "right", decimals: 2 }
]
};
//problems with asynchoronus call back
var response = organization_GetAccountManagerDetailEarningsAccountData(row.data(), purl2, pcontext);
if (response.success === "true") {
for (var i = 0; i < response.value.length; i++) {
for (var j = 0; j < response.value[i].Securities.length; j++) {
var itemRow2 = {};
itemRow2["Security ID"] = response.value[i].Securities[j].SecurityId;
itemRow2["Trades"] = response.value[i].Securities[j].Trades;
itemRow2["Buy Qty"] = response.value[i].Securities[j].BuyQuantity;
itemRow2["Sell Qty"] = response.value[i].Securities[j].SellQuantity;
itemRow2["Total Brkg"] = response.value[i].Securities[j].Effective_Brokerage;
itemRow2["Online Brkg"] = response.value[i].Securities[j].Online_Brokerage;
arrForTable2.push(itemRow2);
totalBrokerage = totalBrokerage + parseFloat(response.value[i].Securities[j].Effective_Brokerage);
totalSelfServiceBrokerage = totalSelfServiceBrokerage + parseFloat(response.value[i].Securities[j].Online_Brokerage);
}
totalBrokerage = Math.round(totalBrokerage * 100) / 100;
totalSelfServiceBrokerage = Math.round(totalSelfServiceBrokerage * 100) / 100;
totalRetailBrokerage = Math.round(totalRetailBrokerage * 100) / 100;
var itemRow1 = {};
itemRow1["Account ID"] = response.value[i].AccountId;
itemRow1["Account Name"] = response.value[i].AccountName;
itemRow1["..."] = '<div class="alert alert-info" role="alert">' + buildHtmlTable(arrForTable2, 'table2x' + j, settings) + '<p>Total Brokerage ' + numberWithCommas(totalBrokerage) + '</p></div>';
arrForTable1.push(itemRow1);
arrForTable2 = [];
totalBrokerage = 0;
totalRetailBrokerage = 0;
totalSelfServiceBrokerage = 0;
}
tr.removeClass('loading');
htmlTable1 = buildHtmlTable(arrForTable1, 'table1x' + i);
row.child(htmlTable1).show();
tr.addClass('shown');
}
else {
row.child('<table><tr><td>' + response.value[0].AccountId + '</td></tr></table>').show();
tr.addClass('shown');
};
}
} catch (e) {
console.log(e.message);
}
});
The Problem:
Firefox nicely shows the Progress image after the user clicks it, but Edge and Chrome does not show. Both browsers crossed this piece of code when I was debugging from developer tools of the respective browser.
Its browser compatible problem? Is there a solution for it? Help me please.
In case of chrome there is such an issue while showing the loading bar while making a server call. Please make the following changes where you are making the service call. First add the class loading to the table
tr.addClass('loading');
After that make the service call by giving a timeout function
setTimeout(function(){
var response = organization_GetAccountManagerDetailEarningsAccountData(row.data(), purl2, pcontext);
......
//Your service calls and response call backs
},1);
On providing a timeout (say 1ms), Chrome will get the time to bind the loading bar to DOM, In other case the DOM Object is not available to show the spinner.

How to select columns (across more panes) in Highcharts / Highstocks

I have this example: http://jsfiddle.net/qzprvohr/1/
What i'm trying to achieve - if i click (just once) to some column, i need to select all columns which has the same x-axis value. Currently it works just for clicked one, the rest is unselected. Also is there any possibility to use some background color for selected columns (not for column itself). Something like xAxis.crosshair.color & xAxis.crosshair.width do for hover state.
I tried something like this to select all columns (but it does not work properly):
plotOptions: {
series: {
allowPointSelect: true,
cursor: 'pointer',
point: {
events: {
click: function (event)
{
var selectedCategory = this.category;
var chart = this.series.chart;
for (var i = 0; i < chart.series.length; i++)
{
for (var j = 0; j < chart.series[i].data.length; j++)
{
if (typeof chart.series[i].data[j] !== "undefined" &&
chart.series[i].data[j].category == selectedCategory)
{
chart.series[i].data[j].select(true, true);
}
}
}
}
}
}}}
I played a bit with the example and i think i found the solution. If I use setTimeout function for selection then all selected column will stay in selected state. Also i used plotBands for another background color. Example here: http://jsfiddle.net/qzprvohr/2/
plotOptions: {
series: {
allowPointSelect: true,
cursor: 'pointer',
point: {
events: {
click: function (event) {
var clickedPoint = this;
setTimeout(function () {
var selectedCategory = clickedPoint.category;
var chart = clickedPoint.series.chart;
for (var i = 0; i < chart.series.length; i++) {
for (var j = 0; j < chart.series[i].data.length; j++) {
if (typeof chart.series[i].data[j] !== "undefined" && chart.series[i].data[j].category == selectedCategory) {
chart.series[i].data[j].select(true, true);
chart.xAxis[i].removePlotBand('selection' + i)
chart.xAxis[i].addPlotBand({
color:'red',
from: selectedCategory - 40000000,
to: selectedCategory + 40000000,
id: 'selection'+i
});
}
}
}
}, 0);
}
}
}
}
}

Categories

Resources