Is there a way to set Fusionchart graph "data" property only. Because currently when you set the the data at a latter stage, you need to pass the full json object which has both "data" and "chart" properties.
Below is my sample code;
FusionCharts.ready(function () {
var ageGroupChart = new FusionCharts({
id: 'total-users',
type: 'pie2d',
renderAt: 'chart-container',
width: '450',
height: '300',
dataFormat: 'json',
"chart": {
"caption": "Sample Graph",
"enableSmartLabels": "0",
"showPercentValues": "1",
"showTooltip": "0",
"decimals": "1",
"theme": "ocean"
},
"data":null
});
ageGroupChart.setJSONUrl( "http://www.example.com/GetData.php" );
ageGroupChart.render();
});
As you can see I'm setting the data from a online source. I'd prefer if the online source does not need to send the "chart" property along with the data. So I can separate the UI look and feel from data-source.
Any Ideas?
I'm using the following function throught XLMhttpRequest calls:
function updateChart(data) {
var jsonData = {
"chart": {
// Some rendering options
"caption": caption,
"subcaption": ""
},
"data": data
};
// First time I initialize my chart
if (FusionCharts("myChartId") === undefined) {
var chart = new myChartId({
// Some rendering options
swfUrl: "Charts/MSLine.swf",
id: "myChartId",
width: "100%",
height: "280px",
dataFormat: 'json'
});
chart.setJSONData(jsonData);
chart.render("myContainerId");
} else
// Then I just update
FusionCharts("myChartId").setJSONData(jsonData);
}
I call the updateChart function into my success callback:
success: function(data, request) {
try {
var d = JSON.parse(data);
updateChart(d.chart);
// Other job...
var event = new CustomEvent("dataReceivedFromAjax", {"detail": d});
document.dispatchEvent(event);
} catch (e) {
window.console.warn("Wrong format JSON data received");
window.console.warn(data);
}
}
Of course you may adapt my code to your case (for instance I'm using JsonData rather than JsonUrl).
Related
I'm having a few issues getting a JSON array to be processed correctly by a JQPlot graph for some reason. I suspect that the array is being interpreted as a single value and not as a sequence of values.
I have a function that makes an ajax call to a php script. The php script computes the graphing data and echo's it back to the user like so:
$retdata = array();
$retdata['date'] = array($ann_dates);
$retdata['close'] = array($closeperdiff);
$retdata['high'] = array($highperdiff);
$retdata['low'] = array($lowperdiff);
echo json_encode($retdata);
Here is the ajax call on the client side:
function getgraph(symbol)
{
var datastring = "symbol=" + symbol;
$.ajax({
type: "POST",
url: "quickview.php",
data: datastring,
dataType: "html",
success: function( data ) {
drawgraph(data);
},
error: function(){
alert('Error somewhere');
}
});
}
Now, finally my JQPLot function 'drawgraph' is called and the data is passed. I'm using JSON.parse to separate the data, I just can't work this into JQPlot correctly. When I run this it essentially just display the first number of the first bar. I suspect the dates are a single string of one long value.
I have tried different variations of " [ ] " in the jqplot function but to no avail. I'm a little stumped!
function drawgraph(garray)
{
var obj = JSON.parse(garray);
//alert(obj["high"]) displays: 1,3,2,1,0,1
//alert(obj["date"]) displays: 2015-05-29,2015-05-12,2015-04-30,2015-03-30,2015-02-27,2015-02-26
s1 = obj["high"];
s2 = obj["low"];
s3 = obj["close"];
ticks = obj["date"];
plot2 = $.jqplot('chart1', s1, s2, s3, {
title:'Bar Chart with Custom Colors',
// Provide a custom seriesColors array to override the default colors.
seriesColors:['#D1FFC2', '#ffCCCC', '#aeaeae'],
renderer:$.jqplot.BarRenderer,
seriesDefaults: {
renderer:$.jqplot.BarRenderer,
pointLabels: { show: true }
},
legend: {
// This renderer is needed for advance legends.
renderer: jQuery.jqplot.EnhancedLegendRenderer,
show: true,
location: 's',
placement: 'outside',
// Breaks the ledgend into horizontal.
rendererOptions: {
numberRows: '1',
numberColumns: '3',
barWidth: 25,
barPadding:-10,
barMargin: -10
},
seriesToggle: true
},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: [ticks]
}
}
});
$('#chart1').bind('jqplotDataHighlight', function (ev, seriesIndex, pointIndex, data) {
$('#info2').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data);
}
);
$('#chart1').bind('jqplotDataUnhighlight',
function (ev) {
$('#info2').html('Nothing');
}
);
}
I'm trying to change columns dynamically in my Alloy UI DataTable - depending on what button is selected, columns are changed depending on which data is returned.
My columns get updated, however the actual data is never included in the table. When I don't define any columns both the columns and data are returned - I of course want control of how my columns are displayed and want to set their attributes
Below is my code:
var dataTable = new Y.DataTable({ //Defining Datatable with no columns preset
editEvent: 'dblclick',
plugins: [{
cfg: {
highlightRange: false
}]
});
button.on(
'click', //On Click...
function() {
var category = $(this).attr("id"); //value retrieved from id of button selected
dataSource = new Y.DataSource.IO({source: '/searchMyData
dataSource.sendRequest({
dataType: 'json',
on: {
success: function(e) {
response = e.data.responseText;
setColumnNames(category); //Set the Columns...
data = Y.JSON.parse(response);
dataTable.set('data', data);//Then the Data
dataTable.render('#my-container');
},
failure: function() {
alert(e.error.message);
}
}
});
function setColumnNames(tabName){ //Defining Columns
var columns1 = [
{ key: 'id', label: 'ID', width: '70px' },
{ key: 'name', label: 'Name', width: '70px' }
];
var columns2 = [
{ key: 'id', label: 'ID', width: '70px' },
{ key: 'addr', label: 'Address', width: '70px' }
];
switch (category) {
case "person":
dataTable.set('columns', columns1);
break;
case "address":
dataTable.set('columns', columns2);
break;
default:
console.log('');
}
There's no issue with the data returning from the ajax request, only when it comes to loading it to the table with a new set of columns defined. I've tried the reset() method on both columns and data on each click, but no luck.
It turns out the keys returned from my request were being capitalized and included underscores (just how they're defined in the database) - I've also noticed defining the columns key is case sensitive. If I changed a single character from lower case to upper than the column would not display data.
I'm trying to display a new Highcharts. Usually I use data from local server and i'm able to load data this way:
data : <php echo $jsonEncoded['values']?>,
The problem is : I have to load data from a remote server and it doesn't work! I really don't understand why...
You will find below my code :
$.ajax({
url: 'myurl',
type: 'GET',
dataType : 'json',
success: function(json, statut){
data_day = json['day'];
data_values = json['js'];
data_start = json['start'];
options = {
chart: {
type: 'area',
renderTo: 'container_health',
},
titile: {
text: "text",
},
yAxis: {
title: {
text: 'Pourcentage'
},
max: 100,
},
series : [{
name: "test",
data: data_values,
pointStart: Data.UTC(data_start),
pointInterval: 24*3600*1000
},
]
};
chart = new Highcharts.Char(options);
}
Then I have 3 alerts:
alert(chart.series[0].pointInterval); //display well the date
alert(chart.series[0].data[0].y); //display undefined
alert(data_values); //display well values
So it seems, I don't have a problem when I want to access directly to a data from my JSON object (json['start']) but it seems it doesn't work when I try to access to my array from json['js']...
Is it a problem from Highcharts or the way to access to data?
EDIT :
All data don't work in options btw.
BR,
I'm trying out Kendo charts with angular, and I have problem displaying data, here is my code:
HTML:
<div kendo-chart="rchart" data-k-options="chartOptions" data-role="chart" class="k-chart" style="position: relative;"></div>
Javascript:
resultService.getResult().then(function (resultResponse) {
$scope.data = resultResponse.data;
$scope.oldReps = _.pluck($scope.data.TreningScores.Item1, 'Item2');
$scope.newReps = _.pluck($scope.data.TreningScores.Item2, 'Item2');
$scope.categories = _.pluck($scope.data.TreningScores.Item1, 'Item1');
});
$scope.chartOptions = {
legend: {
position: "bottom"
},
seriesDefaults: {
type: "column"
},
series: [{
name: "Total Visits",
data: $scope.oldReps
}, {
name: "Unique visitors",
data: $scope.newReps
}],
valueAxis: {
line: {
visible: false
}
},
tooltip: {
visible: true,
format: "{0}"
}
};
The problem is chart isn't updated after data is fetched from server, I've tried refreshing chart like this (but with no luck):
$scope.chart = {
refreshChart : function() {
$scope.rchart.refresh();
},
};
And calling this method in:
resultService.getResult().then(function (resultResponse) {});
And I've also tried to define $scope.chartOptions inside same function, but nothing. Is there any way to fix this ?
It's not well documented, but to get a UI control with remote data-binding to update after data has been returned from a server requires both watching the collection for updates from the Angular side and rebinding the data object to its respective UI control from the Kendo side.
In your controller, watch for changes to your data objects using $watchCollection, and update the objects/properties which are bound to those collections:
// API call
$http.get('...').success(function(data){
$scope.data = data;
});
// KendoUI config object
$scope.chart = {
dataSource: {
data: $scope.data
}
};
// Watch for changes to $scope.data
$scope.$watchCollection('data', function(newData) {
// Update data bindings with changes
$scope.chart.dataSource.data = newData;
});
In your view, define the object your UI control should be bound to when changes are made via the k-rebind Angular-Kendo directive:
<div kendo-chart k-options="chart" k-rebind="chart"></div>
Here is an example of a chart bound to remote data:
http://codepen.io/micjamking/pen/4980a5e22cbd4de01264fadae5f25f06
The use of $watchCollection to track and assign the dataSource.data in the accepted answer and others is a needlessly convoluted approach.
Here's a straightforward implementation:
view:
<div kendo-chart k-theme='metro' k-options="chart" k-rebind="chart"></div>
controller:
$scope.chart = {
dataSource: new kendo.data.DataSource({
data: [{ title: "Loading", value: 100, color: '#EFEFEF' }]
}),
series: [{ field: 'value', categoryField: 'title', padding: 0, holeSize: 25 }],
seriesDefaults: { type: 'donut', startAngle: 90 }
};
Using the dataSource.data() method instead of assigning dataSource.data as an array is the key here:
payrollService.load(userId).then(function (result) {
$scope.chart.dataSource.data(result.items); //where result.items is an array like so:
//[
// { title: "Net Pay", value: 60, color: '#6BAE4B' },
// { title: "Taxes", value: 15, color: '#ED6347' },
// { title: "Deductions", value: 25, color: '#8161C2' }
//]
});
Codepen Demo:
http://codepen.io/TaeKwonJoe/pen/WGOpEv
I think your problem is that $scope.chartOptions is set before the data of the resultService is retrieved. Angular is returning an empty array in this case and filling in the data later.
But $scope.chartOptions not not updated with new data.
You could try with
$scope.$watchCollection('oldReps', function(newData, oldData) {
$scope.chartOptions.series[0].data = newData;
});
$scope.$watchCollection('newReps', function(newData, oldData) {
$scope.chartOptions.series[1].data = newData;
});
So chartOptions are updated if oldReps or newReps have changed.
I had a similiar problem and $watchCollection saved my day (Caching data and updating another object for an chart does not work)
I'm using Extjs 4 with the MVC architecture.
I have a python script that outputs this Json Data :
{
"data": [
{
"inAnalysis": 3,
"inQuest": 2,
"inDevelopment": 6,
"total": 12,
"inValidation": 1,
"Month": 1303
},
{
"inAnalysis": 1,
"total": 5,
"Month": 1304,
"inDevelopment": 4
}
],
"success": true,
"metaData": {
"fields": [
{
"name": "inAnalysis"
},
{
"name": "inQuest"
},
{
"name": "inDevelopment"
},
{
"name": "inValidation"
},
{
"name": "isDuplicate"
},
{
"name": "New"
},
{
"name": "total"
}
],
"root": "data"
}
}
I want the fields of my MetaData to be used as the chart series, so I have a store like this :
Ext.define('Proj.store.ChartData', {
extend: 'Ext.data.Store',
autoload: true,
proxy: {
type: 'ajax',
url : 'data/getParams.py',
reader: new Ext.data.JsonReader({
fields:[]
}),
root: 'data'
}
And to add series to the chart I did this :
var chart = Ext.widget('drawchart');
var fields = [];
chartStore.each(function (field) {
fields.push(Ext.create('Ext.data.Field', {
name: field.get('name')
}));
});
chartModel.prototype.fields.removeAll();
chartModel.prototype.fields.addAll(fields);
var series = [];
for (var i = 1; i < fields.length; i++) {
var newSeries = new Ext.chart.BarSeries({
type: 'column',
displayName: fields[i].name,
xField: ['Month'],
yField: fields[i].name,
style: {
mode: 'stretch',
color: this.chartColors[i + 1]
}
});
series.push(newSeries);
chart.series = series;
};
chart.bindStore(chartStore);
chart.redraw();
chart.refresh();
But It's not working, I think the fields array is always empty...
Any help would be appreciated:
Swapping or reloading a store would be easy, however you'd have a very hard time reconfiguring axes and series a posteriori... Ext's chart just don't support that. It would be possible to replace the axis in the myChart.axes collection, and same for series, and then with a careful study of the code, replace remove the existing sprites, etc. However that's a fool's path since, for once your code will be very fragile against future evolutions of Ext's chart code (which happen), and second there is a far more easier and reliable solution. That is creating a new chart, remove the old one, put the new one in its place, and pouf! The user won't see the difference.
You're not giving a lot of information about your code, so I'll work a solution out of the Bar chart example.
First, you need to fix your store:
Ext.define('Proj.store.ChartData', {
extend: 'Ext.data.Store',
//autoload: true,
autoLoad: true, // there was a type in there
fields: [], // was missing
proxy: {
type: 'ajax',
url : 'data/getParams.py',
// better to inline the proxy (lazy init)
reader: {
type: 'json'
,root: 'data' // and root is an option of the reader, not the proxy
}
// reader: new Ext.data.JsonReader({
// fields:[]
// }),
// root: 'data'
}
});
Then, let's enrich your response a bit in order to minimize the prior client-side knowledge of the model to none. I've added a totalField and a categoryField to the metaData node, that we'll use for the axis and series:
{
"data": [
{
"inAnalysis": 3,
"inQuest": 2,
"inDevelopment": 6,
"total": 12,
"inValidation": 1,
"Month": 1303
},
{
"inAnalysis": 1,
"total": 5,
"Month": 1304,
"inDevelopment": 4
}
],
"success": true,
"metaData": {
"totalField": "total",
"categoryField": "Month",
"fields": [
{
"name": "Month"
},
{
"name": "inAnalysis"
},
{
"name": "inQuest"
},
{
"name": "inDevelopment"
},
{
"name": "inValidation"
},
{
"name": "isDuplicate"
},
{
"name": "New"
},
{
"name": "total"
}
],
"root": "data"
}
}
Please, notice that the proxy will catch the metaData in the response automatically and reconfigure its store's (implicit) model accordingly... so you don't need your gloubiboulga to do it yourself. It is also worth noting that the reader will keep a copy of the raw response data in its rawData property; that will be useful to get the custom information we've added.
Now that we have a proper store that will receive a detailed response, let's use it:
new Proj.store.ChartData({
listeners: {
load: replaceChart
}
});
That will trigger the replaceChart method, that will create a brand new chart from the meta and data given by the server and destroy and replace the old one. Here's the function:
function replaceChart(chartStore) {
// Grab the name of the total & category fields as instructed by the server
var meta = chartStore.getProxy().getReader().rawData.metaData,
totalField = meta.totalField,
categoryField = meta.categoryField;
// Build a list of all field names, excluding the total & category ones
var fields = Ext.Array.filter(
Ext.pluck(chartStore.model.getFields(), 'name'),
function(field) {
return field !== categoryField && field !== totalField;
}
);
// Create a pimping new chat like you like
var chart = Ext.create('Ext.chart.Chart', {
store: chartStore,
legend: true,
axes: [{
type: 'Numeric',
position: 'bottom',
fields: [totalField]
}, {
type: 'Category',
position: 'left',
fields: [categoryField]
}],
series: [{
type: 'bar',
axis: 'bottom',
label: {
display: 'insideEnd',
field: fields
},
xField: categoryField,
yField: fields,
stacked: true // or not... like you want!
}]
});
// Put it in the exact same place as the old one, that will trigger
// a refresh of the layout and a render of the chart
var oldChart = win.down('chart'),
oldIndex = win.items.indexOf(oldChart);
win.remove(oldChart);
win.insert(oldIndex, chart);
// Mission complete.
}
Try to clear lines cache of unused series:
Ext.Array.each(chart.series.items, function(item){
if(!item.items.length){
item.line = null;
}
});