Extjs line graph - extjs

I want to visualize different company data in different colors against date of a line graph.
The problem is the number of companies will change.
Let's say the input data will be like
data: [{ date: '2018-12-20', company1: 10, company2: 5, },{ date: '2018-12-21', company1: 10, company2: 10 }]
To visualize it the model will be like
Ext.define('ABC.model.Job', {
extend: 'Ext.data.Model',
fields: [
{name: 'DATE', type: 'auto'}
{name: '1', type: 'int'}
{name: '2', type: 'int'}
],
proxy: {
type: 'ajax',
noCache: false,
actionMethods: {'read': 'POST'},
api: {
read: utils.createUrl('api', 'read'),
},
reader: {
type: 'json',
root: 'data'
},
listeners: {
exception: function(proxy, response, operation) {
App.showHttpError('Job ', response);
}
}
}
});
And the view portion of axes will be
Ext.define('ABC.view.Job', {
extend: 'Ext.container.Container',
requires: [
'ABC.store.Job',
],
border: false,
layout: {type:'vbox', pack:'start', align:'stretch'},
initComponent: function() {
var me = this;
me.jobStore2 = Ext.create('ABC.store.Job');
Ext.apply(me, {
items: [
{
xtype: 'chart',
store: me.jobStore2,
style: 'background: #fff',
insetPadding: 40,
animate: true,
shadow: false,
flex: 2,
minHeight: 400,
legend: {
position: 'top',
boxStrokeWidth: 0,
labelFont: '12px Helvetica'
},
axes: [{
type: 'Numeric',
position: 'left',
fields: ['1'],
grid: true,
minimum: 0,
}, {
type: 'Category',
position: 'bottom',
fields: ['DATE'],
grid: true,
}],
series: [{
type: 'line',
axis: 'left',
title: '1',
xField: 'DATE',
yField: '1',
style: {
'stroke-width': 4
},
},
{
type: 'line',
axis: 'left',
xField: 'DATE',
border: false,
flex:1,
title: ['2'],
yField: ['2'],
style: {
'stroke-width': 4
},
}
]
}
});
me.callParent(arguments);
}
});
What if the data contains lots of companies. How can I change the series? Instead of giving the detail of y axis again and again

For ease of maintenance, you can just create an array containing the company names, and map it into both fields and axes:
var companies = ['company1', 'company2', ...];
Ext.create('Ext.data.Store', {
fields: [{
name: 'DATE',
type: 'auto'
}].concat(
companies.map(function(companyName) {
return {
name: companyName,
type: 'int'
};
})
)
});
...
series: companies.map(function(companyName) {
return {
type: 'line',
axis: 'left',
title: '1',
xField: 'DATE',
yField: companyName,
style: {
'stroke-width': 4
},
}
});
...

Related

How to use HTML tags in a Chart Legend?

How can use HTML tags in a chart legend while using title to apply custom legend text?
If we apply something like this title:['Your<b>New</b><br />Label'] the tags are just written as plain text.
Ext.application({
name: 'Fiddle',
launch: function () {
var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'data', 'data2'],
data: [{
'name': 'metric one',
'data': 10,
'data2': 2
}, {
'name': 'metric two',
'data': 27,
'data2': 5
}]
});
Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 500,
height: 300,
animate: true,
store: store,
legend: {
position: 'right'
},
axes: [{
type: 'Numeric',
position: 'left',
fields: ['data', 'data2'],
label: {
renderer: Ext.util.Format.numberRenderer('0,0')
},
title: 'Sample Values',
grid: true,
minimum: 0
}, {
type: 'Category',
position: 'bottom',
fields: ['name'],
title: 'Sample Metrics'
}],
series: [{
type: 'column',
axis: 'left',
highlight: true,
stacked: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function (storeItem, item) {
this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data') + ' $');
}
},
label: {
display: 'insideEnd',
'text-anchor': 'middle',
field: 'data',
renderer: Ext.util.Format.numberRenderer('0'),
orientation: 'vertical',
color: '#333'
},
xField: 'name',
yField: ['data', 'data2'],
title: ['Your<b>New</b><br />Label']
}]
});
}
});

Match a serie in a chart with ComponentQuery

I'm using ExtJS 4 with MVC. I have a chart with two series: line and column. When clicking a column I need to trigger an event.
In the controller, I used the following query to match the column series, but doesn't work.
this.control({
'#companyChartItemId[series[type=column]]': {
itemmouseup:this.onItemMouseUp
}
});
Any thoughts how could I match it?
Below is my code:
app/view/company/Chart.js
Ext.define('Market.view.company.Chart', {
extend: 'Ext.chart.Chart',
xtype: 'companyChart',
requires: ['Market.store.HistoricalMarketData'],
theme: 'Category1',
store:'HistoricalMarketData',
initComponent: function() {
this.callParent();
},
axes: [{
type: 'Numeric',
position: 'left',
fields: ['close'],
title: 'Price',
grid: true
}, {
type: 'Numeric',
position: 'right',
fields: ['volume'],
title: 'Volume',
grid: true
}, {
type: 'Category',
position: 'bottom',
fields: ['time'],
title: 'Month of the Year'
}],
series: [{
type: 'column',
axis: 'right',
xField: 'time',
yField: 'volume',
highlight: true,
markerConfig: {
type: 'cross',
size: 3
}
}, {
type: 'line',
axis: 'left',
smooth: false,
fill: false,
fillOpacity: 0.8,
xField: 'time',
yField: 'close'
}]
});
app/controller/ChartController.js
Ext.define('Market.controller.ChartController', {
extend:'Ext.app.Controller',
stores:['MarketData'],
init: function() {
this.control({
'#companyChartItemId[series[type=column]]': {
itemmouseup:this.onItemMouseUp
}
});
},
onItemMouseUp: function (item) {
//do something
}
});
I would just configure the listener/response function where you define your series. You can add listeners as a config in your series, check out the doc:
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.chart.series.Series-cfg-listeners

Ext.js chart series and axis

Suppose I have some data that I want to display on an Ext.js bar chart and I want my data to revolve around a custom value, "1.0" for example, on the y-axis (versus traditionally "0.0").
Meaning, the picture below has negative values represented with inverted bars, I would like values less than "1.0" to show as an inverted bar on the chart.
Is there a setting that I can set to acheive this? If so, would it be in the series and the axis definition? Maybe the chart itself?
The code for the chart displayed is below:
Ext.require('Ext.chart.*');
Ext.require(['Ext.Window', 'Ext.fx.target.Sprite', 'Ext.layout.container.Fit', 'Ext.window.MessageBox']);
Ext.define('CPI', {
extend: 'Ext.data.Model',
fields: [{
name: 'ReportingPeriod',
type: 'string'
}, {
name: 'CPI_P',
type: 'decimal'
}, {
name: 'CPI_C',
type: 'decimal'
}]
});
var store1 = Ext.create('Ext.data.Store', {
model: 'CPI',
data: [{
ReportingPeriod: 'Period1',
CPI_P: '1.9',
CPI_C: '1.2'
}, {
ReportingPeriod: 'Period2',
CPI_P: '1.2',
CPI_C: '1.1'
}, {
ReportingPeriod: 'Period3',
CPI_P: '0.1',
CPI_C: '0.5'
}, {
ReportingPeriod: 'Period4',
CPI_P: '-0.5',
CPI_C: '0.6'
}, {
ReportingPeriod: 'Period5',
CPI_P: '-0.9',
CPI_C: '0.8'
}, {
ReportingPeriod: 'Period6',
CPI_P: '-1.0',
CPI_C: '-0.6'
}, {
ReportingPeriod: 'Period7',
CPI_P: '-1.1',
CPI_C: '-0.7'
}, {
ReportingPeriod: 'Period8',
CPI_P: '-1.5',
CPI_C: '-0.8'
}]
});
var chart = Ext.create('Ext.chart.Chart', {
style: 'background:#fff',
animate: true,
theme: 'Category1',
store: store1,
width: 300,
height: 300,
renderTo: 'chart',
axes: [{
type: 'Numeric',
position: 'left',
fields: ['CPI_P', 'CPI_C'],
title: 'CPI',
grid: true
}, {
type: 'Category',
position: 'bottom',
fields: ['ReportingPeriod'],
title: 'Reporting Period'
}],
series: [{
type: 'column',
axis: 'left',
xField: 'ReportingPeriod',
yField: 'CPI_P',
markerConfig: {
type: 'cross',
size: 3
},
renderer: function(sprite, record, attr, index, store) {
var value = (record.get('CPI_P') >> 2) % 2;
var color = ['rgb(213, 70, 121)',
'rgb(44, 153, 201)'
][value];
return Ext.apply(attr, {
fill: color
});
}
}]
});
chart.show();
UPDATE
If I add a minimum to y-axis I get closer (sort of)
...
axes: [{
type: 'Numeric',
position: 'left',
fields: ['CPI_P', 'CPI_C'],
title: 'CPI',
grid: true,
minimum: 1,
}....
It's the right idea, because the bars now are relevant to the number 1, but I obviously need to keep the bars on the graph.
What has seemed to work is subtracting 1 from my data and adding 1 to the labels.
axes: [{
type: 'Numeric',
position: 'left',
grid: true,
maximum: 1.0, //will render to 2.0
fields: ['PeriodAmount', 'CumulativeAmount'],
label:{
renderer:function(v){
return (v+1).toFixed(2);
}
}
}...]
This is a viable work around for me, but I wouldn't consider this an elegant answer since it isn't very configurable for custom values. For example, changing this to -1 or 2 would require more work than just changing a simple setting.

Error Parsing XML Data for Area Chart

I am receiving the following parsing error. I know the javascript code works because I have swapped out the xml integration with a static JsonStore. Can you spot what I am doing wrong?
Thank you in advance for any suggestions.
Error: Problem parsing d="L790,518.887301636L120,518.887301636Z" results-graph3.htm:1111
Error: Problem parsing d="Z"
The XML File:
<?xml version="1.0" encoding="utf-8"?>
<fundGrowthData>
<growthData>
<Year>1991</Year>
<asOfDate>December 31, 1991</asOfDate>
<Dividends>10000</Dividends>
<Distribution>10000</Distribution>
</growthData>
<growthData>
<Year>1992</Year>
<asOfDate>December 31, 1992</asOfDate>
<Dividends>10655</Dividends>
<Distribution>10740</Distribution>
</growthData>
<growthData>
<Year>1993</Year>
<asOfDate>December 31, 1993</asOfDate>
<Dividends>12146</Dividends>
<Distribution>12297</Distribution>
</growthData>
</fundGrowthData>
The Javascript:
var store = Ext.create('Ext.data.Store',{
autoLoad: true,
fields: ['Year','Dividends','Distribution'],
proxy: {
type: 'ajax',
url: 'pathtoXML',
reader: {
type: 'xml',
record: 'growthData'
}
}
});
Ext.onReady(function () {
Ext.create('Ext.chart.Chart', {
renderTo: Ext.get("js-chart"),
width: 800,
height: 600,
store: store,
axes: [
{
type: 'Numeric',
grid: true,
position: 'left',
fields: ['Dividends', 'Distribution'],
title: 'Sample Values',
grid: {
odd: {
opacity: 1,
fill: '#ddd',
stroke: '#bbb',
'stroke-width': 1
}
},
minimum: 0,
adjustMinimumByMajorUnit: 0
},
{
type: 'Category',
position: 'bottom',
fields: ['Year'],
title: 'Sample Metrics',
grid: true,
label: {
rotate: {
degrees: 315
}
}
}
],
series: [{
type: 'area',
highlight: true,
axis: 'left',
xField: 'Year',
yField: ['Dividends', 'Distribution'],
style: {
opacity: 0.93
}
}]
});
});
Since xml by default is a string, I had to add the type attributes to the Ext.data.Store
var store = Ext.create('Ext.data.Store',{
autoLoad: true,
fields: [
{name : "Year", type: "int"},
{name : "Dividends", type: "int"},
{name : "Distribution", type: "int"}
],
proxy: {
type: 'ajax',
url: 'pathToXml',
reader: {
type: 'xml',
record: 'growthData'
}
}
});

Give a different color to each category item on Sencha Bar Chart

I'm kind of stuck with this thing. What I want to do is to give each bar on a sencha chart a different color. This is what I have so far:
And this is my code for it:
Ext.setup({
tabletStartupScreen: 'tablet_startup.jpg',
phoneStartupScreen: 'phone_startup.jpg',
tabletIcon: 'icon-ipad.png',
phoneIcon: 'icon-iphone.png',
glossOnIcon: false,
onReady: function() {
Ext.regModel('Retail', {
fields: [
{name: 'id', type: 'string'},
{name: 'quantity', type: 'int'}
]
});
var retailStore = new Ext.data.JsonStore({
model: 'Retail',
proxy: {
type: 'ajax',
url: 'getData.php',
reader: {
type: 'json',
}
},
autoLoad: true
});
console.log(retailStore);
new Ext.chart.Panel({
id: 'chartCmp',
title: 'Stock Example',
fullscreen: true,
dockedItems: {
xtype: 'button',
iconCls: 'shuffle',
iconMask: true,
ui: 'plain',
dock: 'left'
},
items: {
cls: 'stock1',
theme: 'Demo',
legend: {
position: {
portrait: 'right',
landscape: 'top'
},
labelFont: '17px Arial'
},
interactions: [{
type: 'panzoom',
axes: {
left: {
maxZoom: 2
},
bottom: {
maxZoom: 4
}
}
}],
animate: false,
store: retailStore,
axes: [{
type: 'Numeric',
position: 'bottom',
fields: ['quantity'],
title: 'Quantity'
}, {
type: 'Category',
position: 'left',
fields: ['id'],
title: 'Products'
}],
series: [{
type: 'bar',
axis: 'right',
xField: 'id',
yField: ['quantity'],
}]
}
});
}});
I know there should be some way to "cheat" the chart by adding an extra dimension to it, just as it is done here:
http://dev.sencha.com/deploy/touch-charts-1.0.0/examples/Bar/
There each year represents a new product. I'd like to do the same with mine, each product representing a different dimension.
You can use the renderer function of a serie. You just have to change attributes.fill to the color you want for each bar. Here is an example : http://bl.ocks.org/3511876 and the code :
Ext.setup({
onReady: function() {
var data = [];
for (var i = 0; i < 10; i++) {
data.push({
x: i,
y: parseInt(Math.random() * 100)
});
}
var colors = ['blue', 'yellow', 'red', 'green', 'gray'];
var store = new Ext.data.JsonStore({
fields: ['x', 'y'],
data: data
});
var chart = new Ext.chart.Chart({
store: store,
axes: [{
type: 'Category',
fields: ['x'],
position: 'left'
}, {
type: 'Numeric',
fields: ['y'],
position: 'bottom'
}],
series: [{
type: 'bar',
xField: 'x',
yField: 'y',
axis: 'bottom',
renderer: function(sprite, record, attributes, index, store) {
attributes.fill = colors[index%colors.length];
return attributes;
}
}]
});
new Ext.chart.Panel({
fullscreen: true,
chart: chart
});
chart.redraw();
}
});

Resources