Flexicious Ultimate - Flex DataGrid Right Click Support

clock July 18, 2014 06:32 by author Flexicious

This has got to be among the most requested features. For the longest time, there was no clean way to provide built in support for right click. Flex has always had a acrimonious relationship with right click. There are a few implementations that interact with the browser and do some javascript trickery to make this work, but nothing has been clean enough for us to provide as a out-of-the-box solution.

So finally when earlier this year we Flash player provided official support for right click, we were able to tap into this new feature and provide a nice way to get you right click support, with a few easy properties and events.

 

  1. Set enableCustomContextMenu="true"
  2. Define your customContextMenuItems="{['Sample Item']}"
  3. Optional, Define itemRightClick event. where you can customize the list of customContextMenuItems if it is different for each cell.
  4. Define itemRightClickMenuSelect event, where you handle the right click menu selection response. 
Lets see what this looks like:

And here is the code that makes this happen:


RightClick.mxml (2.94 kb)

 

Enjoy!



Flexicious Ultimate - Flex DataGrid with rapid inserts and updates

clock July 14, 2014 20:26 by author Administrator

Recently, while working with a customer on optimizing some performance issues, we came across a scenario, where the customer wanted to rapidly update the grid with new data coming from the server. This is a rather complicated use case to accomodate, since the default behavior of the grid is to rebuild itself in response to additions, deletions etc in the dataprovider. It also is quite resource intensive to do so, because usually additions or deletions means you have to rebuild the sort, rerun all filters, update page indexes, and a lot of internal cached information that makes the grid extremely performant needs to be rebuilt. 

We already have the TraderView example that demonstrates how to respond to rapid updates. We do this by turning off the rebuildGridOnDataProviderChange flag, which basically means grid will not respond to changes in dataprovider, and instead will depend on you to explicitly ask it to update via either the rebuild() method or the rebuildBody method. However, in that example, we simlpy call targeted refresh cell calls, to update specific cells that need to be updated. This makes it possible for the grid to respond to a numerous updates per second.

However, keep in mind that with updates to the rows already drawn, there is no need to rebuild the internal index (unless ofcourse, you want to sort, which means you will need to rebuild the index). Basically the caveat to keep in mind is that both for insert and updates, if you want to sort, page, or filter again, there is no way to consume a large number of such operation in subsecond time frames. And this is not a limitation of the grid, but just the amount of time it takes to sort, filter and page an array (even without a grid involved) make it prohibitively expensive to perform this operation multiple times a second.

This brings us to the actual implementation of this use case. Since for this customer, we are inserting rows at the top (as new data comes in, it pushes everything else down), it makes it a lot easier, since we simply do the same thing that the grid would have done, that is, update the index. 

Lets take a quick look at the code that does this:

protected function insertTimerHandler(event:TimerEvent):void

                  {

                        fdg.rebuildGridOnDataProviderChange=false;//so we dont rebuild the index when we change the dataprovider

                        var chg:Number=getRandom(-10,10);

                        //we add it to the dataprovider, this should not affect the grid.

                        //we are adding at index 0

                        var newStock:Object={"id":stocks.length,"symbol":"NEW TICK" + stocks.length, "name":"NEW Ticker with symbol"+stocks.length

                              ,"last":getRandom(20,30),"change":chg+"%","tickUp":(chg>0)};

                        stocks.addItemAt(newStock,0);

                       

                        var rowPos:RowPositionInfo = new RowPositionInfo(

                              newStock,//the data object

                              0, //row index of the data object (0 because we are adding it at the top, you can add it anywhere

                              0,//vertical position of the data object (rowIndex * rowHeight) assuming no variable row height. Or you could lookup the verticalPos of the item above me, and add his height to that number to get this number

                              fdg.rowHeight,//same height rows. For variable row height, you can calculate this

                              fdg.columnLevel, //the top level. If you are adding a child object, you can use the appropriate inner level

                              RowPositionInfo.ROW_TYPE_DATA //type of row. For inner level rows, you can add Header, footer, filter, pager ,renderer rows

                              );   

                        for each(var existingRowPos:RowPositionInfo in fdg.bodyContainer.itemVerticalPositions)

                        {

                              existingRowPos.rowIndex +=1;

                              existingRowPos.verticalPosition += fdg.rowHeight;//push everything down.

                        }

                        for each(var row:RowInfo in fdg.bodyContainer.rows){

                              //now go through all the drawn rows, and update their y property

                              row.y=row.rowPositionInfo.verticalPosition;

                        }

                        fdg.bodyContainer.itemVerticalPositions.splice(0,0,rowPos);//add item at index 0.

                        fdg.bodyContainer.recycle(fdg.columnLevel,false,fdg.rowHeight,false);//now make sure the body draws the row

                        fdg.bodyContainer.placeComponents();//update the cell positions

                        if(stocks.length%5==0){

                              //this will paint the cell background

                              //this is very slighty heavier than other methods, so dont call it as frequently.

                              //may be call it every 2 seconds or so

                              fdg.bodyContainer.invalidateCells();

                        }

                  }

 

                 

 

Here is the sample :

 

TraderView.mxml (9.67 kb)

 

And here is the screenshot: