dynamically changing chart series extjs 4 - javascript

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;
}
});

Related

Highcharts not displaying data on live site

I'm writing a stacked bar chart that is working fine on my local machine, however when it is running on a live server it doesn't plot any of the data points. I've considered that it could be the api is taking longer on the live site to get the data, or maybe highcharts is not loading fast enough, but the x-axis populates the values correctly and the library is loading locally (also happens with CDN).
I can even log the values of the chart series and see everything fine. It just doesn't display any data with a line designating 0 on the Y axis. Anyone have any idea what the issue could be?
$.getJSON( 'URL TO API', function(data){
// Sample data output
// data = [
// { 'name' : 'Items', data : [ 'item1', 'item2', 'item3'] }
// { 'name' : 'losses', data : [2, 3, 1] }
// { 'name' : 'Wins', data : [5, 2, 0] }
// ]
var chart = new Highcharts.Chart({
chart: {
type: 'bar',
renderTo: 'chart',
},
title: {
text: 'Wins and Losses'
},
xAxis: {
categories: data[0]['data']
},
yAxis: {
min: 0,
allowDecimals: false,
title: {
text: 'Total'
}
},
legend: {
reversed: true
},
plotOptions: {
series: {
stacking: 'normal',
}
},
series: [
{
name : data[1]['name'],
data : data[1]['data']
},
{
name : data[2]['name'],
data : data[2]['data']
},
]
});
});

Getting JSON from Google for Highmaps

I'm pretty rusty with JavaScript, so I'm hoping someone can help me out. I'm working with Highmaps and would like to link the map to data in a Google Spreadsheet. (It's a U.S. map of counties which will be updated regularly, so having it all in the script itself is a little unwieldy.)
This is what my code looks like now:
<script type="text/javascript">
var example = 'us-counties',
theme = 'default';
(function($) { // encapsulate jQuery
$(function() {
var data = [{
"code": "us-al-001",
"name": "Autauga County, AL",
"value": 0
},
…
{
"code": "us-pr-153",
"name": "Yauco Municipio, PR",
"value": 0
}],
countiesMap = Highcharts.geojson(Highcharts.maps['countries/us/us-all-all']),
lines = Highcharts.geojson(Highcharts.maps['countries/us/us-all-all'], 'mapline'),
options;
// Add state acronym for tooltip
Highcharts.each(countiesMap, function(mapPoint) {
mapPoint.name = mapPoint.name + ' County, ' + mapPoint.properties['hc-key'].substr(3, 2);
});
series: [{
name: 'County',
mapData: countiesMap,
data: data,
joinBy: ['hc-key', 'code'],
tooltip: {
enabled: true,
positioner: function () {
return { x: 0, y: 250 };
},
pointFormat: '{point.name}',
borders: 0.5
},
borderWidth: 0.5
}, {
type: 'mapline',
name: 'State borders',
data: [lines[0]],
color: 'white'
}, {
type: 'mapline',
name: 'Separator',
data: [lines[1]],
color: 'gray'
}]
};
// Instanciate the map
$('#container').highcharts('Map', options);
});
$(document).ready(function() {
$("#view-menu").click(function(e) {
$("#wrap").toggleClass("toggled");
});
$("#sidebar-close").click(function(e) {
$("#wrap").removeClass("toggled");
});
});
})(jQuery);
</script>
Of course, since there's over 3,200 counties, I'd rather store that data elsewhere and pull it into the var data = [] string, but I'm not sure how to do that.
Any help would be appreciated.
Although this isn't something I've done, it looks like this should be relatively straightforward to do (although nothing is as simple as it looks of course).
There is an API for Google Sheets (https://developers.google.com/google-apps/spreadsheets/) and you can Google examples of how to retrieve data - this one looks clear (https://developers.google.com/gdata/docs/json) although it does point out that there are newer versions of some of the relevant APIs.
If you pull in the JSON data from the Google Sheet you then just need to put the values into the 'value' element of your data variable. You could do all of that within your main function or do it separately and pass it to your function as a parameter.

Set 2d json to highcharts

I use highcharts for draw charts. I have 2d json object and I don't know how to set this object to highcharts. And this is my json object data:
And I want my chart like this picture(column-parsed example of highchart):
And this is my code:
$.ajax({
url:"../../teachersem",
type:"get",
data:{
id:$.trim(tableData[0])
},
success:function(data){
$('div[class|="col-md-7 col-md-offset-3"]').css("display","none");
//console.log(data.accept);
//console.log(data.fail);
var accept=new Array();
var fail =new Array();
for (i = 0; i < data.accept.length; i++){
accept.push([data.accept[i].year, parseInt(data.accept[i].count)]);
alert("accept: "+data.accept[i].year+" "+parseInt(data.accept[i].count));
}
//console.log(accept.toString());
for (i = 0; i < data.fail.length; i++){
fail.push([data.fail[i].year, parseInt(data.fail[i].count)]);
alert("fail: "+data.fail[i].year+" "+parseInt(data.fail[i].count));
}
$('#container').highcharts({
chart: {
type: "column"
},
title: {
text: "Student data"
},
xAxis: {
allowDecimals: false,
title: {
text: "Branch of studies"
}
},
yAxis: {
title: {
text: "Number of students"
}
},
series: [{
data: [accept,fail]
}],
});
},
error:
alert('error!')
})
});
But this has any result? please help,thank u!
You actually want two series: data parameters (one for each column).
The first column will be the accept data and the second column will be your fail data since I am guessing that your category label which in the example image is Apples will be a Branch of Studies.
Your series should look something similar to the following:
series: [{
name: "Accept",
data: accept,
},
{
name: "Fail",
data: fail,
}]
Your accept and fail arrays are currently arrays of arrays, but they can actually be a simple list as seen in the Highcharts demo here. You can then specify in the xAxis parameter the categories: that are your Branch of Studies.

ExtJS 5 Pie Chart Not Rendering Using Remote Store

I have a basic pie chart in ExtJS 5. The issue I am having is that the chart renders with a static JsonStore but won't render properly with a remote data.store?
Here is my code:
View (Chart)
Ext.define('APP.view.core.graphs.Countytotals', {
extend: 'Ext.Panel',
alias: 'widget.countytotalchart',
id: 'countyTotalsGraph',
width: 650,
initComponent: function() {
var me = this;
// Doesn't work?
var countyStore = Ext.create('APP.store.Countytotalsgraph');
// Works
var store = Ext.create('Ext.data.JsonStore', {
fields: ['COUNTY', 'AMOUNT'],
data: [{
'COUNTY': 'London',
'AMOUNT': 10.92
}, {
'COUNTY': 'Lancashire',
'AMOUNT': 6.61
}, {
'COUNTY': 'Kent',
'AMOUNT': 5.26
}, {
'COUNTY': 'West Yorkshire',
'AMOUNT': 4.52
}, {
'COUNTY': 'Nottinghamshire',
'AMOUNT': 4.01
}, {
'COUNTY': 'Other',
'AMOUNT': 68.68
}]
});
var chart = new Ext.chart.PolarChart({
width: '100%',
height: 500,
insetPadding: 50,
innerPadding: 20,
legend: {
docked: 'bottom'
},
listeners: {
afterrender: function (chart) {
if (chart.isVisible()) {
countyStore.load();
chart.redraw();
}
}
},
interactions: ['itemhighlight'],
store: countyStore,
series: [{
type: 'pie',
angleField: 'AMOUNT',
label: {
field: 'COUNTY',
display: 'outside',
calloutLine: {
length: 60,
width: 3
// specifying 'color' is also possible here
}
},
highlight: true,
tooltip: {
trackMouse: true,
renderer: function(storeItem, item) {
this.setHtml(storeItem.get('COUNTY') + ': ' + storeItem.get('AMOUNT') + '%');
}
}
}]
});
me.items = [chart];
this.callParent();
}
});
Store
Ext.define('APP.store.Countytotalsgraph', {
extend: 'Ext.data.Store',
model: 'APP.model.Countytotalsgraph',
autoLoad: false,
storeId: 'countyTotalsGraphStore',
proxy: {
type: 'ajax',
url : '/dashboard/countytotals',
method : 'POST',
reader: {
type: 'json',
rootProperty: 'data'
}
},
listeners: {
beforeload: function(store, eOpts) {
//if ( this.data.items.length ) {
//Ext.getCmp('optionsGrid').getView().refresh();
//}
store.proxy.extraParams = {
percentage: 'true'
}
}
}
});
Model
Ext.define('APP.model.Countytotalsgraph', {
extend: 'Ext.data.Model',
fields: ['COUNTY', 'AMOUNT']
});
This is how is renders with the static store:
This is how it renders with the remote store:
I am on the latest version of the GPL although the charts were built using Sencha CMD and the "sencha ant build" command in the sencha-charts directory.
Why does the static store display it (well still there is still an issue regarding the legend at the bottom) but the remote json not?
Iv'e tried to load the store after it the chart is rendered and is visible as I have seen a previous post regarding holding off on loading the store to give the chart time to render but this did not work:
listeners: {
afterrender: function (chart) {
if (chart.isVisible()) {
countyStore.load();
chart.redraw();
}
}
},
Thanks in advance :)
Nathan
Probably a bug in Ext.
The chart colors are set in Ext.chart.AbstractChart#updateColors. This is a "config" method, that is called automatically when setColors is called, and also from the constructor, when the config is initialized.
In your case, it is only called at construction time, before the remote store has been loaded; and it happens that polar series need to know the number of records in the store in order to know how many colors it must used (unlike other kind of charts that rely on number of axis or so).
Here's the code of that method:
updateColors: function (newColors) {
var me = this,
colors = newColors || (me.themeAttrs && me.themeAttrs.colors),
colorIndex = 0, colorCount = colors.length, i,
series = me.getSeries(),
seriesCount = series && series.length,
seriesItem, seriesColors, seriesColorCount;
if (colorCount) {
for (i = 0; i < seriesCount; i++) {
seriesItem = series[i];
// Ext.chart.series.Polar#themeColorCount uses store.getCount()
// so seriesColorCount will be 0
seriesColorCount = seriesItem.themeColorCount();
// ... hence seriesColor will be an empty array
seriesColors = me.circularCopyArray(colors, colorIndex, seriesColorCount);
colorIndex += seriesColorCount;
seriesItem.updateChartColors(seriesColors);
}
}
me.refreshLegendStore();
}
You could probably get it working by creating the chart after the load event of the store, but that's kind of kinky given your usage is as intended, and the bug will probably get smashed in a coming release.
For now, a possible fix is to override the onRefresh of the chart, that is called, well, when the store is refreshed, and force colors to be updated at this time:
Ext.define(null, {
override: 'Ext.chart.PolarChart'
,onRefresh: function() {
this.callParent(arguments);
var colors = this.getColors();
if (colors) {
this.updateColors(colors);
}
}
});

Treeview checkbox selection with graph updation is not working properly

In my project i have chart and treeview while pageload chart update is not working properly means here in treeview only two checkboxes are checked in pageload but chart is displaying all the field values.i need to display only checkbox checked field values in chart while pageload,( after page-load it's working fine).
here is the fiddle: http://jsfiddle.net/RHh67/64/
My chart code:
$("#myChart").kendoChart({
theme: $(document).data("kendoSkin") || "default",
dataSource: {
data: tmpData2,
sort: {
field: "date",
dir: "asc"
},
schema: {
model: {
fields: {
date: {
type: "date"
}
}
}
}
},
title: {
text: "My Date-aware Chart"
},
legend: {
position: "bottom"
},
seriesDefaults: {
type: "line",
labels: {
visible: true
},
missingValues: "gap"
},
series: series,
valueAxis: [{
name: "A",
labels: {
format: "{0}%"
}
},
{
name: "B",
labels: {
format: "{0}D"
}
}],
categoryAxis: {
type: "Date",
field: "date",
axisCrossingValue: [0, 1000]
}
});
Define a redrawChart that refreshes the Chart with the new series as:
function redrawChart() {
var chart = $("#myChart").data("kendoChart");
var checkedSeries = [];
$("#treeview").find(":checked").each(function () {
var nodeText = $(this).parent().parent().text();
$.each(series, function (index, series) {
if (series.field == nodeText) {
checkedSeries.push(series);
}
});
});
chart.options.series = checkedSeries;
chart.refresh();
}
This functions needs to be invoked:
On your tree change.
After setting the initial visible series.
In addition, move the selection of the initial series to the end of the JavaScript code. I mean, first initialize treeview and chart and only then initialize the initial values.
tree.dataItem(".k-item:nth(2)").set("checked", true);
tree.dataItem(".k-item:nth(3)").set("checked", true);
updateChks();
redrawChart();
The complete running version is in here http://jsfiddle.net/OnaBai/RHh67/68/

Categories

Resources