Home » ActionScript 3.0, Flex

Filtering Flex chart data, by consuming XML data

21 March 2011 One Comment
Share on Facebook

In this tutorial we are going to see how to filter Flex Chart data by consuming a XML data. Knowledge of creating custom MXML component is must before starting this tutorial. Chart filtering will be useful when creating dashboard application, where user can display selected data as Charts.

Tutorial details:

Difficulty: Intermediate
Using: Flex Builder (MXML and Actionscript 3.0)

Filter Flex Chart Final Output:

 

Filter Flex chart using XML

Download source files | View demo online:

 

Download flex source files

View Flex online demo

 

Setting up the XML data:

Copy and paste the below XML data to the XML document, which will be later fetched by the Flex application. Now you can also pass SharePoint 2010 List as source.

<usage>
	<totalUsage>
		<bizSegment id="Total Consumption on 2008">
			<Business_segment name="China">4081.7</Business_segment>
			<Business_segment name="U.S">2503.5</Business_segment>
			<Business_segment name="Russia">1091.0</Business_segment>
			<Business_segment name="Brazil">1004.5</Business_segment>
			<Business_segment name="Germany">911.3</Business_segment>
			<Business_segment name="Mexico">644.0</Business_segment>
			<Business_segment name="Japan">611.1</Business_segment>
			<Business_segment name="UK">512.8</Business_segment>
			<Business_segment name="Poland">356.2</Business_segment>
			<Business_segment name="Spain">342.3</Business_segment>
			<Business_segment name="Ukraine">287.2</Business_segment>
			<Business_segment name="South Africa">247.5</Business_segment>
		</bizSegment>
		<bizSegmentAverage id="Total Consumption on 2007">
			<Business_segment name="China">3913.0</Business_segment>
			<Business_segment name="U.S">2492.1</Business_segment>
			<Business_segment name="Russia">1074.9</Business_segment>
			<Business_segment name="Brazil">1008.6</Business_segment>
			<Business_segment name="Germany">918.9</Business_segment>
			<Business_segment name="Mexico">637.4</Business_segment>
			<Business_segment name="Japan">628.0</Business_segment>
			<Business_segment name="UK">534.7</Business_segment>
			<Business_segment name="Poland">350.2</Business_segment>
			<Business_segment name="Spain">364.1</Business_segment>
			<Business_segment name="Ukraine">284.7</Business_segment>
			<Business_segment name="South Africa">252.6</Business_segment>
		</bizSegmentAverage>
	</totalUsage>
</usage>

Note: The XML data is formed from the below URL.
http://www.geographic.org/country_ranks/beer_consumption_country_ranks_2008.html

Entire code for Flex Chart Filter data:

Idea of the application is to filter the data provider(XML data), which will be reflected on the Flex chart. Please follow the detailed explanation in below steps.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="800" minHeight="400"
				xmlns:View="View.*"  creationComplete="collatrixSource.send()" >
	<mx:Script>
		<![CDATA[
			import Controller.ChartFilterEvent;
			import Model.ModelLocator;
			import View.ItemFilter;
			import flash.net.navigateToURL;
			import mx.charts.CategoryAxis;
			import mx.charts.ColumnChart;
			import mx.charts.series.ColumnSeries;
			import mx.charts.series.LineSeries;
			import mx.charts.series.PieSeries;
			import mx.collections.ArrayCollection;
			import mx.controls.Alert;
			import mx.rpc.events.ResultEvent;

			private var _model:ModelLocator;
			private var pieChartDP:ArrayCollection;

			[Bindable]
			private var _xml:XML;
			[Bindable]
			private var _pieseries:PieSeries;
			[Bindable]
			private var title_str:String = "2008 Beer Consumption by Country";
			[Bindable]
			private var column_dp:ArrayCollection; 

			private var removedColumn_dp:ArrayCollection = new ArrayCollection();

			private function onDataFetched(e:ResultEvent):void
			{

					_xml = e.result as XML; 

					_model = ModelLocator.getInstance();
					_model.XMLData = _xml

				setGraphData(_xml.totalUsage.bizSegment..Business_segment, _xml.totalUsage.bizSegmentAverage..Business_segment);

				var itemFilter:ItemFilter= new ItemFilter()
				hbox1.addChild(itemFilter)
				itemFilter.addEventListener("removeItem", handleClickedItem);

 			}
			private function handleClickedItem(e:ChartFilterEvent):void
			{
				//trace("CLicked:::"+e.isSelected,e.itemName);
				if(e.isSelected)
					addCollectionItem(e.itemName);
				else
					removeCollectionItem(e.itemName);
			}

			private function addCollectionItem( itemName:String ):void
			{
				for(var count:int=0; count<removedColumn_dp.length; count++)
				{
					var obj:Object = removedColumn_dp.getItemAt( count, 0);
					if(obj.BusinessSegment == itemName)
					{
						column_dp.addItem(removedColumn_dp.removeItemAt(count));
						column_dp.refresh();
					}
				}
			}
			private function removeCollectionItem( itemName:String ):void
			{

				for(var count:int=0; count<column_dp.length; count++)
				{
					var obj:Object = column_dp.getItemAt( count, 0);
					if(obj.BusinessSegment == itemName)
					{
						removedColumn_dp.addItem(column_dp.removeItemAt(count));
						column_dp.refresh()
					}
				}

			}

			private function setGraphData(_list:XMLList, lineList:XMLList):void
			{
				column_dp = new ArrayCollection();
				var _len:Number = _list.length();

				for(var count:int=0; count<_len; count++)
				{
					var obj:Object = {BusinessSegment:_list[count].@name,Usage:Number(_list[count].text())}
					column_dp.addItem(obj)
				}

				var line_dp:ArrayCollection = new ArrayCollection();
				var lineListLen:Number = lineList.length();
				for(var index:int=0; index<lineListLen; index++)
				{
					var lineObj:Object = {BusinessSegment:lineList[index].@name,Usage:Number(lineList[index].text())}
					line_dp.addItem(lineObj);
				}

				var lineSeries:LineSeries = new LineSeries();
				lineSeries.dataProvider = line_dp;
				lineSeries.yField = "Usage";
				lineSeries.xField = "BusinessSegment";
				lineSeries.displayName = '2008 Beer Consumption by Country'
				lineSeries.setStyle("showDataEffect", rearrangeData);

				var series1:ColumnSeries = new ColumnSeries();
				series1.dataProvider = column_dp;
				series1.yField = "Usage";
				series1.xField = "BusinessSegment";
				series1.displayName = '2007 Beer Consumption by Country'
				series1.setStyle("showDataEffect", rearrangeData);

				var horAxis:CategoryAxis = new CategoryAxis()
				horAxis.categoryField = "BusinessSegment";

				var columnChart:ColumnChart =  hbox1.getChildByName("columnChart") as ColumnChart;
				columnChart.dataProvider = column_dp;
				columnChart.percentWidth = 80;
				columnChart.percentHeight = 80;
				columnChart.showDataTips = true;

				columnChart.horizontalAxis = horAxis;
				columnChart.series.push( series1 );
				columnChart.series.push( lineSeries );
				columnChart.invalidateSeriesStyles();
				columnChart.series = columnChart.series;
				columnChart.setStyle("columnWidthRatio", 0.85);

				var _legend:Legend =  hbox1.getChildByName("ColumnChartLegend") as Legend;
				_legend.dataProvider = columnChart;  

			}

			private function removeItem(e:MouseEvent):void
			{
				column_dp.removeItemAt(0);
				column_dp.refresh();
			}

		]]>
	</mx:Script>
	<mx:HTTPService id="collatrixSource" url="XML/Collatrix_data.xml" resultFormat="e4x" result="onDataFetched(event)"/>
	<mx:SeriesInterpolate id="rearrangeData" duration="1000" elementOffset="5"/>
	<mx:SeriesSlide direction="right" duration="1000" id="lineChartShowDataEffect"/>

	<mx:Panel width="100%" height="100%">
		<mx:VBox id="box1" width="100%" height="100%">
			<mx:Label text="{title_str}" fontWeight="bold" fontSize="16"/>
			<mx:HBox id="hbox1" width="100%" height="100%">
				<mx:ColumnChart name="columnChart" width="914" height="100%" id="columnchart1">

				</mx:ColumnChart>

				<mx:Legend name="ColumnChartLegend" id="legend1"/>

			</mx:HBox>
		</mx:VBox>
	</mx:Panel>
	<mx:Label text="Flex Chart tutorial by" x="400" y="120"/>
	<mx:Label text="Designscripting.com" x="460" y="137" buttonMode="true" click="{navigateToURL(new URLRequest('http://www.designscripting.com'),'_blank')}"/>

</mx:Application>

Step 1: Create a New Flex Project

Open Flex builder and create a new flex project by “File -> New -> Flex Project”, Enter the project name and the application type may be either dekstop or web application. Web application type is followed in this tutorial. Select Finish button to create the project.

step 2: Set up the User interface

We can either follow code or design mode to create the user interface, follow either one below

Add a column chart and legend component from the components window in Design mode.
Paste the below MXML code in code window.

<mx:Panel width="100%" height="100%">
	<mx:VBox id="box1" width="100%" height="100%">
		<mx:Label text="{title_str}" fontWeight="bold" fontSize="16"/>
		<mx:HBox id="hbox1" width="100%" height="100%">
			<mx:ColumnChart name="columnChart" width="914" height="100%" id="columnchart1">

			</mx:ColumnChart>

			<mx:Legend name="ColumnChartLegend" id="legend1"/>

		</mx:HBox>
	</mx:VBox>
</mx:Panel>

Step 3: Fetch the XML data

Data source for the chart is provided via XML, we are going to use “HTTPService” MXML component to retrive data.

<mx:HTTPService id="collatrixSource" url="XML/Collatrix_data.xml" resultFormat="e4x" result="onDataFetched(event)"/>

Once the data is successfully read, Result Event(onDataFetched) will be triggered.

private function onDataFetched(e:ResultEvent):void
{

		_xml = e.result as XML; 

		_model = ModelLocator.getInstance();
		_model.XMLData = _xml

	setGraphData(_xml.totalUsage.bizSegment..Business_segment, _xml.totalUsage.bizSegmentAverage..Business_segment);

	var itemFilter:ItemFilter= new ItemFilter()
	hbox1.addChild(itemFilter)
	itemFilter.addEventListener("removeItem", handleClickedItem);

 }

In the Result Event above we create the Filter component and Set the graph data source.

Step 4: Set up Chart ItemFilter

Create a new MXML Component which extends a List Component name the Component as “ItemFilter”
On Creation Complete Event, get the XML data and set “FilterItem” as ItemRenderer which is extended from Check box Component.

<?xml version="1.0" encoding="utf-8"?>
<mx:List xmlns:mx="http://www.adobe.com/2006/mxml" dataProvider="{_listData}"
  	 creationComplete="init()" height="270">
  	<mx:Metadata>
	[Event(name="ChartFilterEvent", type="Controller.REMOVECHARTITEM")]
	</mx:Metadata>
<mx:Script>
	<![CDATA[
		import Model.ModelLocator;

		import View.FilterItem;
		import mx.core.ClassFactory;
		import Controller.ChartFilterEvent;

		private var _model:ModelLocator;
		private var _xml:XML;
		[Bindable]
		public var _listData:Array =new Array();

		private function init():void
		{
			_model = ModelLocator.getInstance()
			_xml = _model.XMLData;
			var xmlList:XMLList = _xml.totalUsage.bizSegment..Business_segment;

			for each(var node:XML in xmlList)
			_listData.push(node.@name);

			this.itemRenderer = new ClassFactory(FilterItem);
		}

	]]>
</mx:Script>

</mx:List>

Chart Flex filter

Step 5: Manipulate Filter data

In main MXML, we have created and added listener Event for ItemFilter, Please refer step 3.

private function handleClickedItem(e:ChartFilterEvent):void
{
	//trace("CLicked:::"+e.isSelected,e.itemName);
	if(e.isSelected)
		addCollectionItem(e.itemName);
	else
		removeCollectionItem(e.itemName);
}

Once we check or uncheck the check box in ItemFilter, remove or add the collection item. When we remove or add an item in collection refresh it by calling the “refresh()” method;

private function addCollectionItem( itemName:String ):void
{
	for(var count:int=0; count<removedColumn_dp.length; count++)
	{
		var obj:Object = removedColumn_dp.getItemAt( count, 0);
		if(obj.BusinessSegment == itemName)
		{
			column_dp.addItem(removedColumn_dp.removeItemAt(count));
			column_dp.refresh();
		}
	}
}
private function removeCollectionItem( itemName:String ):void
{

	for(var count:int=0; count<column_dp.length; count++)
	{
		var obj:Object = column_dp.getItemAt( count, 0);
		if(obj.BusinessSegment == itemName)
		{
			removedColumn_dp.addItem(column_dp.removeItemAt(count));
			column_dp.refresh()
		}
	}

}

Step 6: Animate the data change

Create some Flex effect and set time duration for the animation.

<mx:SeriesInterpolate id="rearrangeData" duration="1000" elementOffset="5"/>

Add the effect to the chart using setStyle(), by passing the id

lineSeries.setStyle("showDataEffect", rearrangeData);

Note: Using setStyle() offen will reduce performance of the aplication.

Conclusion:

In this tutorial we have seen how to filter the chart data in Flex. Download the source files of the chart filter.

Note: use the menu File > Import Flex Project(FXP) in Flash Builder.

Add comments for any doubts, thanks for reading.

 

GET THE UPDATES VIA EMAIL

We don't share your email anywhere, grab our rss via feedburner


One Comment »

Leave your response!

Add your comment below, or trackback from your own site. You can also subscribe to these comments via RSS.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

This is a Gravatar-enabled weblog. To get your own globally-recognized-avatar, please register at Gravatar.