Hiho. Been busy these last couple of weeks … For me it’s the first time looking deeper into this whole Flex stuff. And Aron is getting his hand dirty with iPhone development and Google Web Toolkit (GWT). But as the title already says, this post is all about Flex.
Right now, I’m building some Flex-modules that are heavily data-driven – that’s basically why I chose Flex in the first place. After trying to build my own datagrids and excel-like tables in Flash/AS3 I quickly decided to turn to Flex and use the built-in components to get everything working.
So …. after getting to know Flex a little better, I can say one thing for sure: I don’t really like it :)
You got components for almost everything, but if your requirements differ just a bit from the features the flex-components offer, you are screwed. and especially the DataGrid – it’s very easy to get some rows out of your database and display them in the grid, but don’t event try to use complex data … then everything crashes and you have to write dozens ans dozens of ItemRenderers and work-arounds to display the data in the DataGrid.
yadda yadda yadda … I’m still working my butt off to get everything as I want it to be – but I thought I’ll share my thoughts and especially my “tricks” with you.
First of all I want to thank Peter deHaan for his great Flex-blog (http://blog.flexexamples.com/) – I got so many little things off of his blog. I think also there may be some lines of code in the example, that I copied from him. Secondly there is this post, I read about “dynamically adding rows to a DataGrid” that I used as a guide to implement my own DataGrid (http://www.switchonthecode.com/tutorials/adding-dynamic-rows-to-flex-datagrid). So again – thanks to you!
Here are the requirements I had to fulfill for one of my own DataGrids:
- dynamically add rows to DataGrid
- dynamically adjust height of DataGrid
- the user should be able to input money-values
- calculate sum of all inserted values
- use ComboBox within DataGrid as ItemRenderer
- ComboBox should define a time-interval for the money-values
So this is what I came up with – you can see for yourself. (sourceview / rightclick)
Some tricky things were e.g. the dynamic height of the DataGrid – I had to use a custom function to calculate the height every time the data within the DataGrid changed.
private function _calculateHeight():void { if(grid.dataProvider) { var len:int = grid.dataProvider.length; _gridHeight = grid.measureHeightOfItems(-1, len); } }
And then there was the adding of the rows itself – as I mentioned earlier, I found this post about how to add rows dynamically and just adapted it for my purposes.
private function onCollectionChanged(event:CollectionEvent):void { // check if last row is != 0 var obj:Object = _arr.getItemAt(_arr.length-1); if(obj.question != 0 && _arr.length < MAX_EXPENSES) { _arr.addItem({question:0, timeInterval:0, timeIntervalEditable:false, money:0}); return; } // check if timeInterval == 0 for(var i:int = _arr.length-1; i >= 0; i--) { obj = _arr.getItemAt(i); if(obj.question != 0 && obj.timeInterval == 0) { _arr.removeItemAt(i); return; } } // update height _calculateHeight(); _updateTotal(); }
Another problem was the update-process of my own ItemRenderers – e.g. the one with the ComboBox to select the time-interval. After changing the value of the ComboBox the DataGrid never got the COLLECTION_CHANGED event and I couldn’t update the “total” at the bottom of the DataGrid. So back to google and again looking for a solution … I found this somewhere:
private function forceUpdate():void { //log.debug("forceUpdate()"); // Access the collection - listData.owner is the DataGrid and from there you have its dataProvider. var ac:ArrayCollection = (listData.owner as DataGrid).dataProvider as ArrayCollection; data.question = cmb.selectedItem.val; if(cmb.selectedItem.val != 0) { data.timeInterval = 1; data.timeIntervalEditable = true; } // finally, tell the collection the data changed. this will cause the collection to // dispatch its own change event which is then picked up by the main application. ac.itemUpdated(data); }
Now everything worked fine and I could update the “total” everytime the user changed a value in the DataGrid.
For the rest of the code, just check the “view source” of the swf. I haven’t had the time to comment the code in detail, but the code is pretty much self-explanatory – once you got all the pieces together ;)
I haven’t mentioned it, but I’m still working with FlexBuilder3 and not the new “Gumbo“-Release – in which Adobe overhauled all components.
Soooo … hope this post is of any help to you and I spare you the many hours looking for answers that I had to waste.
Cheers