Progressbar in Datagrid Example
Line Break
Author: Roelof (13 Articles) - Author Website
Roelof is a SAP Consultant specialized in Front-End development. In his spare free time he is either developing on the web, playing basketball, watching soccer or traveling. He is also the co-owner of Flex-Blog.com.
In the comments of our previous post about using the ProgressBar, one of our readers asked if a ProgressBar could be used inside a DataGrid.
This is, ofcourse, possible. So we decided to write an example about this.
There are a couple of things you need to know before we start:
- Use an ItemRenderer to show the ProgressBar inside the DataGrid instead of text.
- Create a DataProvider for the DataGrid (in our case we use an ArrayCollection).
- Create an action to start the ProgressBar (in our case we simulate a download).
- Make sure the ArrayCollection is updated on every progress of the ProgressBar.
First we create an ItemRenderer in a seperate ActionScript file (myProgressBar.as):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package { import mx.containers.HBox; import mx.controls.ProgressBar; import mx.controls.dataGridClasses.*; public class myProgressBar extends HBox //This should normally be extends ProgressBar, we are using HBox to have more control over the layout. { private var pb:ProgressBar; public function myProgressBar():void { //Create new ProgressBar Instance pb = new ProgressBar(); //Set some layout things pb.mode = "manual"; pb.percentWidth = 100; pb.labelPlacement = "center"; this.setStyle("verticalAlign","middle"); //Add ProgressBar as child addChild(pb); } override public function set data(value:Object):void { super.data = value; } override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void{ super.updateDisplayList(unscaledWidth, unscaledHeight); pb.setProgress(data.loaded, data.total); } } } |
Then we will use this ItemRenderer inside the DataGrid column.
1 |
<mx:DataGridColumn itemRenderer="myProgressBar" dataField="progress" headerText="Progress" width="180" paddingLeft="5"/> |
To start the ‘fake’ ProgressBar download progress, we are using an Image as a Button inside the DataGrid.
1 2 3 4 5 6 7 8 9 10 |
<mx:DataGridColumn width="112" headerText="Download"> <mx:itemRenderer> <fx:Component> <mx:HBox horizontalAlign="center" verticalAlign="middle"> <s:Label text="{data.file}"/> <mx:Image buttonMode="true" toolTip="'Download'" click="outerDocument.downloadFile()" source="@Embed(source='images/down_alt.png')"/> </mx:HBox> </fx:Component> </mx:itemRenderer> </mx:DataGridColumn> |
Why use outerDocument?
Since the itemRenderer is within another Component, we need to use outerDocument to call a method inside your ‘main’ Component.
Next step was to implement the method downloadFile():
1 2 3 4 5 6 7 |
public function downloadFile():void{ //start timer var timer:Timer = new Timer(500); // add event listener timer.addEventListener(TimerEvent.TIMER, updateProgressBar); timer.start(); } |
Next, implement the eventListener. Inside the eventListener we need to make sure the DataGrid / ArrayCollection gets updated.
1 2 3 4 5 6 7 |
private function updateProgressBar(event:TimerEvent):void{ var myItem:Object; // Add a 'random' number to loaded. To fake the progress.. myDataGrid.selectedItem.loaded += Math.ceil(Math.random() * 5); //refesh arraycollection to refresh the datagrid myArrayCollection.refresh(); } |
Then you are done. Below you will find a working example. For the full source code either use Right Mouse Click -> View Source or scroll down.
Full Source Code:
ProgressBarInsideDatagridExample.mxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" width="500" height="200" initialize="init();" viewSourceURL="srcview/index.html"> <fx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable]private var myArrayCollection:ArrayCollection; private function init():void { // Create instance of myArrayCollection myArrayCollection = new ArrayCollection; // Create new Object var obj:Object = new Object; obj.file = "File 1"; obj.total = 100; obj.loaded = 0; // Add object to myArrayCollection myArrayCollection.addItem(obj); obj = new Object; obj.file = "File 2"; obj.total = 100; obj.loaded = 0; // Add object to myArrayCollection myArrayCollection.addItem(obj); } public function downloadFile():void{ //start timer var timer:Timer = new Timer(500); // add event listener timer.addEventListener(TimerEvent.TIMER, updateProgressBar); timer.start(); } private function updateProgressBar(event:TimerEvent):void{ var myItem:Object; // Add a 'random' number to loaded. To fake the progress.. myDataGrid.selectedItem.loaded += Math.ceil(Math.random() * 5); //refesh arraycollection to refresh the datagrid myArrayCollection.refresh(); } ]]> </fx:Script> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <mx:DataGrid id="myDataGrid" height="200" width="500" dataProvider="{myArrayCollection}"> <mx:columns> <mx:DataGridColumn width="112" headerText="Download"> <mx:itemRenderer> <fx:Component> <mx:HBox horizontalAlign="center" verticalAlign="middle"> <s:Label text="{data.file}"/> <mx:Image buttonMode="true" toolTip="'Download'" click="outerDocument.downloadFile()" source="@Embed(source='images/down_alt.png')"/> </mx:HBox> </fx:Component> </mx:itemRenderer> </mx:DataGridColumn> <mx:DataGridColumn itemRenderer="myProgressBar" dataField="progress" headerText="Progress" width="180" paddingLeft="5"/> </mx:columns> </mx:DataGrid> </s:Application> |
myProgressBar.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package { import mx.containers.HBox; import mx.controls.ProgressBar; import mx.controls.dataGridClasses.*; public class myProgressBar extends HBox //This should normally be extends ProgressBar, we are using HBox to have more control over the layout. { private var pb:ProgressBar; public function myProgressBar():void { //Create new ProgressBar Instance pb = new ProgressBar(); //Set some layout things pb.mode = "manual"; pb.percentWidth = 100; pb.labelPlacement = "center"; this.setStyle("verticalAlign","middle"); //Add ProgressBar as child addChild(pb); } override public function set data(value:Object):void { super.data = value; } override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void{ super.updateDisplayList(unscaledWidth, unscaledHeight); pb.setProgress(data.loaded, data.total); } } } |