Pass c3js chart options to function - javascript

I have several different charts that I am rendering with c3js via ajax, and I currently have a lot of repeated ajax code that I would like to cut down on.
Each ajax call on success generates a c3js chart, but with different display types/options. Is there a way I can have a generic c3js generate and just pass in the options?
$.ajax({
url: url,
data: {'chart': chart, 'start': start, 'end': end},
type: 'post',
dataType: 'json',
beforeSend: function () {
//code
},
success: function (data) {
if (data.success) {
//code
c3.generate({
bindto: '#chart-data',
data: {
columns: data.active,
type: 'area',
groups: [data.groups]
},
axis: {
x: {
type: 'category',
categories: data.span
},
y: {
label: 'Label'
}
}
});
} else {
//code
}
}
});
Repeated several times with various chart data types, groups, columns, axis, etc.
What I want:
var chart_options = {bindto: '#chart-data', data:{columns.data.active} //...
function generateChart(param1, param2, param3, chart_options) {
//do some stuff
//ajax call from above
// ....
// on success:
// c3.generate(chart_options)
}
However when I do it this way, because the data.success is inside the function, and I am passing columns: data.active from outside the function, I receive javascript errors for data[i] column not defined.
Thanks

var chart_options = {bindto: '#chart-data', {data: {type: "area"}} //...}
function generateChart(param1, param2, param3) {
//do some stuff
//ajax call from above
// ....
// on success:
// chart_options.data.colums = data.active;
// chart_options.data.groups = [data.groups];
// same for axes…
// c3.generate(chart_options)
}

Related

How to properly code Javascript / Ajax for use with Chart.js

I have a controller action in my MVC project that creates a json record with the components needed. This is working. The issue I am having is bringing it into a chart.js canvas. This will be a pie chart that shows all the related countries with a count of each. Json has this info. Originally this was setup to use google visualization but I want to use chart.js. I just started using it. Creating charts with static data is no issue but I am pulling the info from a SQL table and creating a json to read from.
I have tried using the same structure and calling the data: data[] but it doesn't work I have also tried data: getData, which is a var for the ajax function. I am getting the data per the council on refresh.
Here is my controller Action
public ActionResult CustomersByCountry()
{
CustomerEntities _context = new CustomerEntities();
var customerByCountry = (from c in _context.Addresses
group c by c.Country into g
orderby g.Count() descending
select new
{
Country = g.Key,
CountCustomer = g.Count()
}).ToList();
return Json(new { result = customerByCountry }, JsonRequestBehavior.AllowGet);
}
And here is the JavaScript/ajax - which is nested in a document.ready function with the rest of the charts.
EDIT - changed Ajax - Still not working
OrdersByCountry()
function OrdersByCountry() {
$.ajax({
url: '/admin/CustomersByCountry',
method: "GET",
dataType: "json",
error: function (_, err) {
console.log(_, err)
},
success: function (data) {
console.log (data);
var customer = $("#customerByCountryPieChart").get(0).getContext("2d");
console.log(customer)
var cpieChart = new Chart(customer, {
type: 'pie',
data: data,
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
}
});
};
Edit - The now working code is below.
I changed it to get states instead of country, just to clear up possible confusion. It made more sense to me to get States rather than Country at this point. This is working - meaning displaying the graph, I still need to work on the labels etc.
OrdersByStates()
function OrdersByStates() {
$.ajax({
url: '#Url.Action("CustomersByStates", "Admin")',
data: JSON,
contentType: "application/json; charset=utf-8",
method: "get",
dataType: "json",
error: function (_, err) {
console.log(_, err)
},
success: function (response) {
console.log(response);
var jsonresult = response
var labels = jsonresult.result.map(function (e) {
return e.State;
});
var data = jsonresult.result.map(function (e) {
return e.CountCustomer;
});;
var ctx = document.getElementById("CustomerByStatePieChart").getContext("2d");
var cpieChart = new Chart(ctx, {
type: 'pie',
data:
{
datasets: [
{
backgroundColor: ["#46BFBD", "#F7464A"],
hoverBackgroundColor: ["#5AD3D1", "#FF5A5E"],
label: "Orders",
data: data,
}]
},
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
}
});
};
});
try:
var cpieChart = new Chart(customer, {
type: 'pie',
data: data.result,
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
the response from the server "data" var on your request is {result: LIST}

unable to create dynamic events in fullcalendar

i have a situation in which i m trying to create events dynamically using the plugin fullcalendar im trying to create events with the help of the ajax call and the data retrieved is in the form of json
when i m trying to create events only event at index 0 is getting created rest of events are not created
the javascript code is as follows
function showData()
{
var ids = showValidData();
if (ids.length != 0)
{
$.ajax({
url: $("#base-url").val() ,
type: 'POST',
data: {'ids': ids},
dataType: 'json',
success: function (response)
{
var data = response.data;
var myevents = [];
if (response.success)
{
$(data).each(function (index, value) {
myevents.push({
title: value.layoutName,
start: value.startDate,
end: value.endDate
});
});
console.log(myevents);
$(".fc-event-container").click();
$('#calendar-example-1').fullCalendar({
events: myevents,});
return;
}
}
});
}
}
Set events when initializing FullCalendar - define the url of the script that returns a json of events from your database (https://fullcalendar.io/docs/event_data/events_function/). If you want to dynamically refresh the calendar , you can add a setInterval ontop:
$(document).ready(function(){
setInterval(function(){$('#calendar').fullCalendar('refetchEvents')}, 30000);
$("#calendar").fullCalendar({
...
events: {
url: 'script.php',
type: 'POST',
data: {
data1: x,
data2: y
},
success : function(response){
// do something
},
}
});
});

Redraw Morris Donut after AJAX call

I'm using Morris Donut for a dashboard I'm working on and retrieving data via AJAX using two date ranges as parameters. The problem I'm facing is when I enter two new date ranges the Donut Chart renders a new one on top of Donut already created upon page load. I've searched about and can see information on using setData(), but I have no idea how to include this within my code.
My Code:
$(document).ready(function () {
var start = $('#SearchStart').val();
var end = $('#SearchEnd').val();
populateDonut(start, end);
});
The search button does the following when clicked:
$('#DateRange').click(function() {
var start = $('#SearchStart').val();
var end = $('#SearchEnd').val();
populateDonut(start, end);
});
Here is the function that is called.
function populateDonut(start, end) {
var param = { start: start, end: end };
$.ajax({
type: "POST",
url: "/WebService.asmx/getDonutData",
contentType: "application/json; charset=utf-8",
dataType: 'json',
async: true,
data: JSON.stringify(param),
success: function (result) {
var data = eval("(" + result.d + ")");
var pieChart = '';
if (data.status == 0) {
var donut = Morris.Donut({
element: 'pieChart',
data: [
{ label: "Inbound", value: data.inbound },
{ label: "Outbound", value: data.outbound },
{ label: "Unanswered", value: data.unanswered }
],
colors: ['#1ca8dd', '#33b86c', '#ebc142'],
resize: true,
formatter: function (x) { return x + "%" }
});
}
}
});
}
Screenshot of what is happening after entering new date ranges:
Try calling $("#pieChart").empty(); before rendering the second chart.
Preferably in here:
$('#DateRange').click(function() {
var start = $('#SearchStart').val();
var end = $('#SearchEnd').val();
// Clear the existing chart before populating new donut
$("#pieChart").empty();
populateDonut(start, end);
});
I tried the below code and it's working with me :
$("#chart-id").empty();
You can use it on each time you call chart data .

$.done() code gets executed before $.when()

In my project I m using 2 versions of JQuery.js, so I resolved the conflict using $.noConflict() for my latest version of JQuery to variable named jq172. Now I have used jq172.when().done()construct to show loading status image until all ajax request are processed completely. The code is as follows.
jq172.when(
DisplayPOXOrderStatistics(fromDate, toDate),
DisplayPOXCompletedOrdersData(fromDate, toDate),
DisplayPOXCompletedOrderPieChart(fromDate, toDate),
DisplayCurrentYearlyTrends())
.done(function (a1,a2,a3,a4)
{
$("#loading").hide();
});
where functions in the jq172.when() are coded as follows,
function DisplayPOXOrderStatistics(fromDate, toDate) {
return $.ajax({
type: "POST",
url: '#Url.Action("DisplayPOXOrderStatistics", "Home")',
dataType: "json",
data: { FromDate: fromDate, ToDate: toDate },
success: function (data) {application code.....}
});
}
function DisplayPOXCompletedOrdersData(fromDate, toDate) {
return $.ajax({
type: "POST",
url: '#Url.Action("DisplayPOXCompletedOrders", "Home")',
data: { FromDate: fromDate, ToDate: toDate },
dataType: "json",
success: function (data) { some code....}
});
}
& rest 2 functions are coded in the same way as above
Now my code in .done() to hide loading image dive should be executed after all 4 ajax call is finished, but currently it gets executed immediately after function call is dispatched. Can anybody figure out the problem in my code.
Thanks in Advance...
Here is the definition of rest 2 functions..
function DisplayPOXCompletedOrderPieChart(fromDate, toDate) {
return $.ajax({
type: "POST",
url: '#Url.Action("POXCompletedOrderPieChart", "Home")',
data: { FromDate: fromDate, ToDate: toDate },
dataType: "json",
success: function (data) {
$('#POXCompletedOrdersPie').empty();
var dataSet = [];
var isDataAvailable = false;
for (var i = 0; i < data.length ; i++) {
var newElement = { label: data[i].Name, data: parseFloat(data[i].ColumnValue), color: Color[i] };
dataSet.push(newElement);
if (newElement.data > 0)
isDataAvailable = true;
}
if (dataSet.length != 0 && isDataAvailable) {
$.plot($("#POXCompletedOrdersPie"), dataSet, {
series: {
pie: {
show: true
}
},
legend: {
show: false
}
});
}
else {
$("#POXCompletedOrdersPie").empty();
$("#POXCompletedOrdersPie").append("<html><p> <b>" + "#Html.Raw(VirtuOxAdvDME.Dashboard_PieChart_POXCompletedOrder_NoData)" + "</b> </p><html>");
}
}
});
}
function DisplayCurrentYearlyTrends() {
$("#DisplayCurrentYear").html($('#selectCurrentYear option:selected').text());
return $.ajax({
url: '#Url.Action("DisplayCurrentYearlyTrends", "Home")',
data: { selectedCurrentYear: $('#selectCurrentYear option:selected').text() },
type: 'POST',
dataType: 'json',
success: function (data) {
var DataValues = [], TickData = [];
var i = undefined;
$.each(data, function (index, item) {
i = (index + 1) * 2;
DataValues.push({ data: [i, item.Value], color: Color[i] });
DataValues.push([i, item.Value]);
TickData.push([i, item.MonthName]);
});
$.plot($("#CurrentYearlyTrendsBar"), [{ data: DataValues, color: "#3D69AA" }],
{
series: { bars: { show: true } },
bars: {
barWidth: 1.5,
align: "center"
},
xaxis: {
ticks: TickData,
axisLabelUseCanvas: true,
labelAngle: -90,
},
yaxis: { axisLabelUseCanvas: true },
grid: { hoverable: true }
});
$("#CurrentYearlyTrendsBar").UseTooltip();
}
});
}
Probably your $.ajax calls (from the old jQuery version) do not return jqXHR objects which implement the Promise interface, a feature that was introduced with v1.5. when would see the objects as plain values then and resolve immediately.
To fix this, use jq172.ajax() instead, or use a (single) up-to-date jQuery and update your legacy code.
this is from the jquery site
in the multiple-Deferreds case where one of the Deferreds is rejected, jQuery.when immediately fires the failCallbacks for its master Deferred. Note that some of the Deferreds may still be unresolved at that point. If you need to perform additional processing for this case, such as canceling any unfinished ajax requests, you can keep references to the underlying jqXHR objects in a closure and inspect/cancel them in the failCallback.
check your ajax calls and make sure no one is getting rejected. You can do this in the
developers console->network tab
generally becomes accessible after pressing F12.

Highscore with jQuery.ajax: How to Initialize / Scope Issue

I'm quite a newbie concerning JS, so this may be a stupid question...
I try to do a Highscore Master/Detail chart (see sample http://jsfiddle.net/VhqaQ/). The data array should be filled with a jQuery.ajax call:
$(function () {
var masterChart,
detailChart,
data=[],
chatter=[],
indizies=[];
$(document).ready(function() {
$.ajax({
url: 'index.php',
data: 'type=1363435001',
dataType: 'json',
success: function(json) {
data = json.range;
scatter = json.scatter;
indizies = json.indizies;
},
error: function (xhr, status, error) {
alert('Status: ' + status +' Error: ' + error);
}
});
// create the master chart
function createMaster() {
masterChart = new Highcharts.Chart({
.......
series: [{
type: 'columnrange',
name: 'Intervall',
pointInterval: 1,
pointStart: 0,
data: data
}],
});
}
........
createMaster();
});
});
But like this the chart stays empty. Is this a scope issue for the data array? Or is data not initialized yet when new Highcharts.Chart( ...) is called?
I tested the ajax part - data is filled properly. So this is not the issue...
Maybe I should put the ajax call somewhere else?
Call createMaster() in the callback of your $.ajax call and pass it the data.
You are currently assuming that at initialization of the ajax call that the data has been returned, which most likely not the case. Placing the function call inside of the callback ensure that your data is present.
$.ajax({
url: 'index.php',
data: 'type=1363435001',
dataType: 'json',
success: function(json) {
data = json.range;
scatter = json.scatter;
indizies = json.indizies;
createMaster(data);
},
error: function (xhr, status, error) {
alert('Status: ' + status +' Error: ' + error);
}
});
// create the master chart
function createMaster(data) {
masterChart = new Highcharts.Chart({
.......
series: [{
type: 'columnrange',
name: 'Intervall',
pointInterval: 1,
pointStart: 0,
data: data
}],
});
}

Categories