11 October 2009 ~ 9 Comments

Data from multiple stores to charts in ExtJs – jQuery flot

Got a comment on my previous post Ext JS Charts and timeaxis:

Hi Nils -
Thanks for the article. We have got two lines within a chart. We are using this for trend analysis. So, one line should show the actual data and the other we want to trend it beyond the actual data. We know how to trend and all. But, can we have two datasets to be used for drawing the lines? Would appreciate any information. Thanks, again.

“Two datasets” – I did some testing based on the Charts package in ExtJs. But, I soon figured out it would not work without lots of work.

Flot charts and multiple stores in ExtJs

But, I have worked with another charts library called flot in a project lately. We even hired Ole Laursen, the guy behind flot, to do some further development on the library. He wrote a method for converting ExtJs Stores to flot data series. The following shows how this can be done. Happy reading.

Basics – setup data stores

This post is based on the Ext JS Charts and timeaxis. The main source is the same, so read read it first if you are just looking for how to make charts in Ext Js.

You will need the following files:
jquery.js
jquery-flot.js

/*
I have defined two div's in a html file: 

The last one just for debug and testing purpose.
*/

	// Defining the fields for the record.
	// For simplicity we use the same fields definition and the same record for both stores.
	var fields = [ {name: 'timestamp', type: 'date'}, 'temperature'];

	// Sets up the record
	var rec = new Ext.data.Record.create([
        { name: 'datetime', type: 'date', dateFormat: 'Y-m-d H:i:s'},
        { name: 'temp' }
    ]);

	// Creates an array with the data
	var data = [
	    ['2009-08-22 00:00:00', 10],
	    ['2009-08-22 01:00:00', 10.2],
	    ['2009-08-22 02:00:00', 10.6],
	    ['2009-08-22 03:00:00', 10.7],
	    ['2009-08-22 04:00:00', 10.8],
	    ['2009-08-22 05:00:00', 10.6],
	    ['2009-08-22 06:00:00', 10.9],
	    ['2009-08-22 09:00:00', 10.6],
	    ['2009-08-22 12:00:00', 11.2],
	    ['2009-08-22 15:00:00', 11.5],
	    ['2009-08-22 18:00:00', 11.7],
	    ['2009-08-22 21:00:00', 11.9]
    ];

    var data2 = [
        ['2009-08-22 00:00:00', 12],
        ['2009-08-22 01:00:00', 12.2],
        ['2009-08-22 02:00:00', 12.6],
        ['2009-08-22 03:00:00', 12.7],
        ['2009-08-22 04:00:00', 12.8],
        ['2009-08-22 05:00:00', 12.6],
        ['2009-08-22 06:00:00', 12.9],
        ['2009-08-22 09:00:00', 12.6],
        ['2009-08-22 12:00:00', 13.2],
        ['2009-08-22 15:00:00', 13.5],
        ['2009-08-22 18:00:00', 13.7],
        ['2009-08-22 21:00:00', 13.9]
     ];

	// Creates an array reader
	var reader = new Ext.data.ArrayReader({}, rec);

	// And finally the store
	var store = new Ext.data.Store({
		fields: fields,
		reader: reader,
		data  : data
	});

	var store2 = new Ext.data.Store({
		fields: fields,
		reader: reader,
		data  : data2
	});

Now we have two stores, with slightly different data.

Setting up flot series

The API docs for flot says the following about the data format for the series:


The data is an array of data series:
[ series1, series2, ... ]
A series can either be raw data or an object with properties. The raw
data format is an array of points:
[ [x1, y1], [x2, y2], ... ]
E.g.
[ [1, 3], [2, 14.01], [3.5, 3.14] ]

So, we now need a method for taking data from ExtJs Stores and convert them to, yeah exactly, arrays.

	function flotDataFromExtStore(store, xField, yField, appendId) {
		function convert(data) {
			if (data === "")
				return null;
			if(data === null)
				return null;

			if (typeof data == "object" && data.constructor == Date)
                // correct with local timezone offset to work-around data being
                // in local time
				return data.getTime() - data.getTimezoneOffset() * 60 * 1000;
			return +data;
		}

		var res = [];
		store.each(function (record) {
			res.push([convert(record.data[xField]),
					  convert(record.data[yField])]);
			if (appendId)
				res[res.length - 1].push(record.id);
		});
		return res;
	}

The next step is to generate the chart and the dataseries based on our two stores:

// I have defined a div element with the id chart
	jQuery.plot(
			document.getElementById("chart"),
			[
                // data from the first store
                flotDataFromExtStore(store, "datetime", "temp"),
                // data from the second store
                flotDataFromExtStore(store2,"datetime","temp")
            ]
    );

That’s pretty much it, you have a perfect working chart with lines from two different Ext data stores.

flot chart based on extjs data store

A working example can be seen here.

Sweet or what?

Further reading

Professional JavaScript Frameworks: Prototype,YUI, ExtJS, Dojo and MooTools
Smashing Jquery
Zend Studio for Eclipse Developer's Guide

9 Responses to “Data from multiple stores to charts in ExtJs – jQuery flot”

  1. vnug 12 October 2009 at 07:35 Permalink

    Nils –

    Thanks for taking time to setup the example. Much appreciated. Would we be able to get source for this? We will also try with this information and see how it goes. Again, thanks.

  2. maksimer 12 October 2009 at 09:13 Permalink

    vnug,
    the source can be found at: http://aboutfrontend.com/wp-content/uploads/2009/10/extjs-flot.html

  3. maksimer 20 July 2010 at 09:50 Permalink

    I got some questions in the Sencha forum (http://www.sencha.com/forum/showthread.php?82630-Charts-jQuery-flot-and-data-from-multiple-extjs-stores&highlight=aboutfrontend) about how to add the charts to panels. As far as I can see this cannot be done directly, since flot is written in jQuery and the rest is ExtJs.

    Of course, there are ways to solve it anyways. The point is that the panel needs to be rendered first, so that you can assign an id to it.

    var renderPanel = new Ext.Panel({
    	renderTo: "chart",
    	html: 'A panel',
    	id: "renderPanel",
    	height: 300,
    	width: 600
    });
    
    
    jQuery.plot(
    	Ext.getDom("renderPanel"), 
    	[
            flotDataFromExtStore(store, "datetime", "temp"),
            flotDataFromExtStore(store2,"datetime","temp")
        ]
    );
    

    Working example can be seen at http://aboutfrontend.com/wp-content/uploads/2009/10/to-panel.html

  4. Kishore 6 October 2010 at 04:09 Permalink

    Hi,
    Can we change the data format??

  5. Kishore 6 October 2010 at 04:11 Permalink

    Hi,
    Can we change the date format??
    It currently display the date in number which is not ideal. Should be something like ‘5/10/2010 2:05:20’.
    How can we do this?

  6. bill 11 January 2011 at 10:09 Permalink

    i’ve been into different tutorials… but still i can’t make it! no chart showed!!!

  7. Nils-Fredrik 11 January 2011 at 10:56 Permalink

    Could you please paste some example code regarding the Ext Charts you have problems with?

  8. Gerald Gentile 29 November 2011 at 22:31 Permalink

    Do you have an issue with spambots comment spamming on your blog? Click http://tinyurl.com/6onsxla for the solution.

  9. Alex 30 March 2012 at 21:33 Permalink

    Is it possible to plot these kind of data from my store1 and store2? (please see below)

    ‘author’ is supposed to go to X Axis and ‘rating’ is supposed to go on Y axis.

    I got your example to work in my workspace, but I’m not sure how to use a category (such as author) for X-axis?

    var store1 = new Ext.data.JsonStore({
    fields:[‘author’, ‘rating’],
    data: [
    {author:’A’, rating: 7 },
    {author:’B’, rating: 2},
    {author:’C’, rating: 2}

    ]
    });

    var store2 = new Ext.data.JsonStore({
    fields:[‘author’, ‘rating’],
    data: [
    {author:’A’, avgrating: 7 },
    {author:’B’, avgrating: 2},
    {author:’C’, avgrating: 2}

    ]
    });

    Thanks!


Leave a Reply