Progressbar in Datagrid Example
Line Break
Author: Roelof (11 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, travelling or just being lazy. 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); } } } |
Related posts:
- Using the ProgressBar with a file download in Flex
- Image as Button in a DataGrid
- Drag and Drop from DataGrid or AdvancedDataGrid to Tree
- Images in DataGrid depending on data
- ArrayCollection Filter Example
Comments
5 Responses to “Progressbar in Datagrid Example”


Nice Work! Great Job!
This worked GREAT! Man! I was really struggling with this for a project I am working on. I approached your blog with the air of a desperate man, but desperation has now turned into gratitude.
Thank you SO much for this sample!
Next question regarding this:
This example uses selectedItem. This means you can only do one progress bar at a time. Is there a way to make this asynchronous instead?
I have just got a blog and use about 50 different plugins. Thank you very much for your plugin. It complete my website
Huh, well this sort of got me on the right track. The thing that this does not accomodate for is the fact the datagrids reuse item renderers. If you have enough items in the datagrid to need to scroll, and you scroll up and down, you will notice that some progress bars will “steal” their progress from other rows. Also, extending HBox will really slow things down. I’d recommend this blog http://blogs.adobe.com/aharui/2007/03/thinking_about_item_renderers_1.html to anyone trying to accomplish this. This should implement IListItemRenderer, and IDropInListItemRenderer and set the progress in a validateNow() override.