Dynamically generated dropdown list breaks web service call - javascript

I have an ASPX dropdown list, that is used in a web service call to generate a graph.
If I manually enter the drop down list entries, the code executes fine, however if I dynamically generate the dropdown list from the SQL server the web service call fails.
Here is how I am generating the dropdown list:
//Populate Customers DDL
string constr = ConfigurationManager.ConnectionStrings["Indigo2.Properties.Settings.ConstrNW"].ConnectionString;
DataTable customers = new DataTable();
using (SqlConnection con = new SqlConnection(constr))
{
try
{
SqlDataAdapter adapter = new SqlDataAdapter("SELECT DISTINCT custid from [Indigo].[dbo].[invoices] WHERE custid='ACC001'", con);
adapter.Fill(customers);
//ddlCustA.DataSource = customers;
//ddlCustA.DataTextField = "custid";
//ddlCustA.DataValueField = "custid";
//ddlCustA.DataBind();
}
catch (Exception ex)
{
// Handle the error
}
}
Here is the HTML
<asp:DropDownList ID="ddlCustA" runat="server" Height="17px" Width="100px" AutoPostBack="True">
</asp:DropDownList>
This is where I call the Web Service
//Code for graph (all in document ready)
$("#btn_line_chart").on('click', function () {
var CustA = $("#ddlCustA").val();
var CustB = $("#ddlCustB").val();
var getYear = $("#ddlYear").val();
var jsonData = JSON.stringify({
custA: CustA,
custB: CustB,
year: getYear
});
$.ajax({
type: "POST",
url: "WebService1.asmx/getLineChartData",
data: jsonData,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess_,
error: OnErrorCall_
});
function OnSuccess_(reponse) {
var aData = reponse.d;
var aLabels = aData[0];
var aDatasets1 = aData[1];
var aDatasets2 = aData[2];
var data = {
labels: aLabels,
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: aDatasets1
},
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: aDatasets2
}]
};
var ctx = $("#myChart").get(0).getContext('2d');
ctx.canvas.width = 750; // setting width of canvas
ctx.canvas.height = 400; // setting height of canvas
var lineChart = new Chart(ctx, {
type: "line",
data: data,
bezierCurve: false
});
}
function OnErrorCall_(repo) {
alert("Woops something went wrong, pls try later !");
}
});
If I manually choose the dropdown list options (like below), it works fine.
<select id="ddlCustA">
<option>ACC001</option>
</select>
When the dropdown list is generated from the SQL server, the web service call fails with the folowing error:
HTTP500: SERVER ERROR - The server encountered an unexpected condition
that prevented it from fulfilling the request. (XHR)POST -
https://localhost:44338/WebService1.asmx/getLineChartData
Any help greatly appreciated.
UPDATE: It seems to be a timing issue. If I add an alert just before the web service calls the ddlCustA variable, ddlCustA shows as "Undefined"
alert($("#ddlCustA").val());

In case it helps anyone else, my solution was the way I was calling the object from Javasctipt. The below code fixed it.
var CustA = document.getElementById('<%= ddlCustA.ClientID %>').value

Related

Chart.js - get base 64 encoded string as variable

I'm creating a chart using the Chart.js library and it's working well. I'm using the .toBase64Image() function to generate a base 64 encoded string of the chart (png data url).
I can see this when I inspect the chart in my browser developer tools, e.g.:
data:image/png;base64,iVBORw0KGgoAAAA etc
I now need to call a URL to another application that will pass the data url as a parameter - I'm just stuck at how to get the data url as a parameter to pass to my URL that I will then call.
Here's my script as it currently stands:
var radarChartData = {
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [3, 2, 1, 5, 6, 8, 5]
},
]
};
window.onload = function() {
window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar(radarChartData, {
responsive: true,
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: 1,
scaleStartValue: 0,
onAnimationComplete: function() {
document.getElementById("canvas").innerHTML = myRadar.toBase64Image();
theURL = "fmp://$/chartingFile?script=getChartToContainer&param=";
window.location = theURL;
}
});
}
I need to append the "data:image/png;base64,iVBORw0KGgoAAAA" string to the 'theURL' variable but can't figure out how to get this as a string?
Managed to work this out as follows:
onAnimationComplete: function() {
document.getElementById("canvas").innerHTML = myRadar.toBase64Image();
var x = document.getElementById("canvas").innerHTML = myRadar.toBase64Image();
theParam = encodeURIComponent(x);
theURL = "fmp://$/chartingFile?script=getChartToContainer&param=" + theParam;
window.location = theURL;
Not sure if it's optimal etc but it's working well so far.

Looping inside variable (json data)

Anyone know how looping json data INSIDE varibale?? Example
var data = {
$.each(data, function(i, item) {
console.log(data[i].PageName);
});​
labels: [dateLoop],
datasets: [{
}]
};
Well that code is didnt work for me. I want looping inside that varibale. Anyway this coding for Chart.js
Why i need looping?? cuase i have filter buyer and date range, if i choose 3 buyer, and date range from january 2016 to May 2016. On data will show data buyer, each data buyer will have value from date range. Exmaple data json
data [Buyer 1] : ["167404", "129770", "113598", "127301", "156868", "634789", "242188", "166312", "169418"];
data [Buyer 2] : ["9580", "22250", "3500", "5558", "254556", "268500", "77750", "69850", "55"];
So what i need how too looping inside variable?? Sorry my bad languange.
Edit probbaly someone dont know what i mean,
example i have pick 2 buyer, Buyer A (Json["data"][0]) and Buyer B (Json["data"][1]) and each that buyer have value (wich this value order by month if i pick January and May, it will show "222","555")
and the code i mean like this :
var data = {
labels: [dateLoop], #ignore this
datasets: [{ label : (Json["data"][0])
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [(value orderby month in Json["data"][0]]
},
{ label : (Json["data"][1])
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [(value orderby month in Json["data"][1]]
}
]
};
That i want it. But i sue each make error. :/
try this, you need 2 loop first loop is for keys and second is for the values inside array
var data = {
'Buyer 1': ["167404", "129770", "113598", "127301", "156868", "634789", "242188", "166312", "169418"],
'Buyer 2': ["9580", "22250", "3500", "5558", "254556", "268500", "77750", "69850", "55"]
}
for(var key in data) {
for (var x in data[key]) {
console.log(data[key][x]);
}
}

Chart.js custom tooltipTemplate index

I have this chart made with Chart.js.
var data = {
labels: ["", "", "", "2015-08-28", "2015-08-29", "2015-08-30", "2015-08-31", ],
websites: ["", "", "", "gamesoutletCrawler", "gamesoutletCrawler", "G2PLAY", "instantgaming", ],
datasets: [{
label: "Best price last 7 days",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [0, 0, 0, 34.5, 36.8, 37.3, 37.99, ]
}]
};
window.onload = function() {
var ctx = document.getElementById("chartkeys").getContext("2d");
window.myLine = new Chart(ctx).Line(data, {
responsive: true,
tooltipTemplate: "<%= data.websites[idx] %>",
scaleLabel: "<%= Number(value).toFixed(2).replace('.', ',') + ' €'%>"
});
}
On my tooltip template, I want to use values from data.websites but I don't know how to pass in the index for my tooltip array. This is not working:
<%= data.websites[idx] %>
idx is wrong, it's not the index the system is using. Any idea what I have to write here to show the index tooltip when you hover on the graph?
If I write <%= data.websites %>, it's showing me all the websites in the array, not the one hovered.
You can use a function instead of a template string
...
tooltipTemplate: function (d) {
return data.websites[data.labels.indexOf(d.label)]
},
...
Note that this requires the labels to be unique, or if there are duplicate labels that it not matter which one is active (for instance, in your data, the first 3 labels are the same but that won't cause any problems because the first 3 entries in the websites array too are the same. If they were different this method will not work)

Draw a Chart.js with ajax data and responsive. A few problems and questions

I am using Chart.js (http://www.chartjs.org/docs/) for charting.
I need to get the data from an Ajax request and the chart to be responsive.
In my HTML code I added a canvas as follows:
<div>
<canvas id="userscreated" class="plot" data-url="/stats/userscreated"></canvas>
</div>
And in my javascript (JQuery) code I have:
var data2;
$.ajax({
url: $('#userscreated').data('url'),
async: true,
dataType: 'json',
type: "get",
}).done(function (data) {
data2 = data;
// Draw chart
var context = $('#userscreated').get(0).getContext("2d");
var wrapper = $('#userscreated').parent();
var width = $('#userscreated').attr('width', $(wrapper).width());
new Chart(context).Line(
{
labels: data.Dates,
datasets: [
{ fillColor: #404040, data: data.Users }
]
},
{ animation: false }
);
});
// Redraw the chart with the same data
$(window).resize(function () {
var context = $('#userscreated').get(0).getContext("2d");
var wrapper = $('#userscreated').parent();
var width = $('#userscreated').attr('width', $(wrapper).width());
new Chart(context).Line(
{
labels: data2.Dates,
datasets: [
{ fillColor: #404040, data: data2.Users }
]
},
{ animation: false }
);
});
PROBLEMS
The chart is not being resized on window resize.
Is there better code to do this? I think I am repeating to much code.
In Google the drawing is fast. In firefox sometimes it hangs for a while.
Is anything wrong with my code?
Should the request be async or not?
You can make async AJAX calls no problem. It's just important that you setup the chart only after the success callback fires. Otherwise, you'll get issues with your canvas context not being defined. The first call to respondCanvas does the initial setup while the subsequent calls do the resizing.
Here is what works for me:
var max = 0;
var steps = 10;
var chartData = {};
function respondCanvas() {
var c = $('#summary');
var ctx = c.get(0).getContext("2d");
var container = c.parent();
var $container = $(container);
c.attr('width', $container.width()); //max width
c.attr('height', $container.height()); //max height
//Call a function to redraw other content (texts, images etc)
var chart = new Chart(ctx).Line(chartData, {
scaleOverride: true,
scaleSteps: steps,
scaleStepWidth: Math.ceil(max / steps),
scaleStartValue: 0
});
}
var GetChartData = function () {
$.ajax({
url: serviceUri,
method: 'GET',
dataType: 'json',
success: function (d) {
chartData = {
labels: d.AxisLabels,
datasets: [
{
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
data: d.DataSets[0]
}
]
};
max = Math.max.apply(Math, d.DataSets[0]);
steps = 10;
respondCanvas();
}
});
};
$(document).ready(function() {
$(window).resize(respondCanvas);
GetChartData();
});
If you want to insert a small delay between calls, you can use a timeout:
$(document).ready(function() {
$(window).resize(setTimeout(respondCanvas, 500));
GetChartData();
});
The delay will make your resizing more responsive in case you have a large dataset on your graph.
you can set that in chart.js
new Chart(context, {
type:"line",
labels: data.Dates,
datasets: [
{ fillColor: #404040, data: data.Users }
]
options: { responsive: false }
});
For those reading this in 2021:
Update for chart.js v3.x.x
Following updated answer for v3.x.x (which is not backwards compatible with v2.x.x)
First, answers to the 4 initial questions:
The chart is not being resized on window resize.
Is there better code to do this? I think I am repeating to much code.
In Google the drawing is fast. In firefox sometimes it hangs for a while. Is anything wrong with my code?
Should the request be async or not?
With current version, it should resize automatically, try it yourself running the snippet below and resizing the browser window.
The trick was to assign your chart to a variable const myLineChart = and then call simply myLineChart.update() when needed. Be aware to assign programmatically the labels and datasets again before calling myLineChart.update(), otherwise data changes would not reflect in chart.
Should be fine now in firefox according to my testings.
Oh yes, absolutely async (either ajax or http-request with callback or promises).
// once the success function of your $.ajax request fires,
// put following code within your success-function
// for now, let's assume sample data
let data2 = {
"Dates" : [
"2021-08-02",
"2021-08-03",
"2021-08-04",
"2021-08-05",
"2021-08-06"
],
"Users": [
6,
4,
3,
8,
2
]
};
// Draw chart
const ctx = document.querySelector('canvas').getContext('2d');
const myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: data2.Dates,
datasets: [{
label: 'Users created',
data: data2.Users,
borderColor: 'green',
backgroundColor: '#404040',
fill: true,
animations: false // <-- now plural, instead of "animation" before
}]
}
});
// Redraw the chart with an added record
function updateData(event) {
event.target.disabled = true;
data2 = {
"Dates" : [
"2021-08-02",
"2021-08-03",
"2021-08-04",
"2021-08-05",
"2021-08-06",
"2021-08-07"
],
"Users": [
6,
4,
3,
8,
2,
12
]
};
// assign programmatically the datasets again, otherwise data changes won't show
myLineChart.data.labels = data2.Dates;
myLineChart.data.datasets[0].data = data2.Users;
myLineChart.update();
};
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- gets you the latest version of Chart.js, now at v3.5.0 -->
<button onclick="updateData(event)">add Data</button>
<canvas width="320" height="240"></canvas>
Indeed
Yes, I'll give you an example.
I dont see anything that might cause an issue. Except that window.resize might be firing rendering a new chart far more often then you want.
No. (I don't really know why, this is more coincidence.)
The code:
window.getVisitCounts = ($canvas) ->
url = Routes.visits_between_project_path($canvas.data('project-id'), {
format: "json",
start: $canvas.data('start'),
end: $canvas.data('end')
})
visits = []
days = []
$.ajax
url: url,
async: false,
dataType: "json",
type: "GET",
success: (data) - >
for point in data.chart.data
visits.push(point.visits)
days.push(point.date)
{
days: days,
visits: visits
}
window.createChartData = (raw) - > {
labels: raw.days,
datasets: [{
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
data: raw.visits,
}]
}
window.setupCanvas = ($canvas, data) - >
newWidth = $canvas.parent().width()
$canvas.prop
width: newWidth
height: 400
options = {
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: Math.ceil(Math.max.apply(Math, data.datasets[0].data) / 10),
scaleStartValue: 0
}
ctx = $canvas.get(0).getContext("2d")
new Chart(ctx).Line(data, options)
$ - > #canvas = $("#analytics-canvas")
if# canvas.length != 0# visits = window.createChartData(window.getVisitCounts(#canvas))
window.setupCanvas(#canvas, #visits)
$(window).on('resizeEnd', - >
setupCanvas(document.canvas, document.visits)
)
$(window).resize - >
if (#resizeTO)
clearTimeout(#resizeTO)
#resizeTO = setTimeout(- >
$(this).trigger "resizeEnd"
500
)

How to add the elements dynamically from the html table for chart.js

Can anyone help with this issue?
I am using chart.js for developing charts into my asp.net mvc C# application.
The issue is I am unable to add the elements dynamically from the html table to the chart.
<canvas id="myChart" width="600" height="400"></canvas> //html5 canvas
<script type="text/javascript">
var ctx = document.getElementById("myChart").getContext("2d");
var data = {
datasets: [
{
fillColor: "rgba(223,104,27,0.5)",
strokeColor: "rgba(220,220,220,1)",
data: getcountdata1()
},
{
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,1)",
data: getcountdata2()
}]
myNewChart = new Chart(ctx).Line(data, options);
The above is working fine, becausse in datasets I am hardcoding the number of elements in datasets, but in reality this should check the HTML table and get the data from the table.
Now the question is how can I make the datasets to get dynamic values based on the number of rows in the table?
For example I have written a Javascript function (I have tried the following coed):
var data:
{
datasets: getdata()
}
function getdata()
{
rows = document.getElementById('tblresult').getElementsByTagName('tbody')[0].getElementsByTagName('tr').length;
for(i=0;i<rows;i++)
{
datasetdata[i] = [
{
fillColor: getrandomfillcolor(),
strokeColor: getrandomstrokecolor(),
data: getcountdata()
}]
}
function getrandomfillcolor()
{
}
function getrandomstrokecolor()
{
}
function getcountdata()
{
}
return datasetdata
}
I have tried several times but was not able to find a solution for this.
You need to pass each row to getcountdata() function
rowsDomElements = document.getElementById('tblresult').getElementsByTagName('tbody')[0].getElementsByTagName('tr');
for(i=0;i<rowsDomElements.length;i++)
{
datasetdata[i] = [
{
fillColor: getrandomfillcolor(),
strokeColor: getrandomstrokecolor(),
data: getcountdata(rowsDomElements[i])
}]
}
function getcountdata(row)
{
//create data as needed
}

Categories

Resources