CheckBox Item Renderer Example for Flex 2

My man A&W had some DataGrid woes. He’s now indoctrinated to the hardest part of Flex / Flash Development: Item Renderers. Adobe deserves credit for making these a lot easier with inline editors and some other nice properties. That doesn’t change the fact that they are f’ing hard and time consuming.

Weirder still is the way you get events from ’em, via event bubbling. Granted, I’m sure rendererIsEditor on the DataGridColumn class works wonders when it works, but at the end of the day, a lot of the itemRenderers and itemEditors you create may need more detail that you want to know about, and bubbling events are a great way to get at that data.

The gist is, you create an itemRenderer class and set one of the DataGrid columns to use it as an itemRenderer. This GUI MXML or ActionScript component emits an event you care about either using the default flash.events.Event class, or one of your own. This event has its bubbles property set to true. As long as its type doesn’t conflict with events the DataGrid is listening for, it’ll bubble up to the form hosting the DataGrid. There is where you handle the event.

The trick is you have to use ActionScript to register for the event because the DataGrid doesn’t know about your custom event; it’s not in its metatags. Therefore, MXML won’t work and AS will.

Source code – Example (Right click to View Source) | ZIP

28 Replies to “CheckBox Item Renderer Example for Flex 2”

  1. Funny you post about this now. If I had any hair I woulda pulled it out dealing with ItemRenderers last night and this morning. Once you ‘get’ the concept though, it makes sense. I think I’ll throw together an example based on my ItemRendering adventures. :)

  2. Nice concise example Jesse. I am having a little trouble understanding what purpose DataGridListData and the corresponding dgld variable serve though. Can you elaborate a bit?

    Thanks,
    Ben

  3. DataGridListData holds the dataField and columnIndex variable. Without those, you have no clue what column, and therefore, what field in your dataProvider your click refers to.

    “I clicked on the 3rd item in the DataGrid according to the rowIndex… but what cell? Was it the ID cell, the name cell, or the isFound cell?”

    I know technically the itemRenderer is used in only one column, so it’s pretty obvious which column it’s referring to, but just in case it’s used in multiple columns, like Aaron’s original example, you need it to be it’s namesake: “Generic”. Meaning, generic enough that it can be used for 2 columns in the same DataGrid and work for instance.

    DataGridListData extends BaseListData, which has the rowIndex, also what you need (which index in the dataProvider your renderer is referring to).

    So, rowIndex for position in dataProvider, dataField for what field in the object in your dataProvider. The rowIndex comes from BaseListData, and the dataField comes from DataGridListData. You need both for a DataGrid.

    A List component only shows one field, even if your items in your dataProvider show many, like the PersonVO for example. It has 3, but a List could only show 1 set via the labelField or labelFunction.

    A DataGrid shows all fields, or those you set explicitly. Therefore, when you click on an item, you need to know:
    – what number in the dataProvider
    – what field is the cell drawing of that item

    The base event class isn’t dynamic, so I can’t add properties to it like I can in AS2. Therefore, I had to make a custom event class.

    I could of used rowIndex and dataField on the event, but it’s not obvious if those are referring to some other control. DataGridListData is pretty obvious; it’s associated with an itemRenderer in a DataGrid. So, the code has clear intent.

    Finally, why use classes at all? Strong-typing. Strong-typing in AS3 is now worth it; you get mad speed. It was just a formality, organization, and intent purpose in AS2. Now in AS3 there is a speed benefit to your code for strong-typing everything.

    Hope that clears it up!

  4. Thanks Jesse, that does clear it up.

    After reading Igor’s comment I went and played with it a bit more and noticed that if you sort by the isKnown column a few times and then start checking and unchecking items, sometimes it will add a fourth row to the DataGrid. I realize this was a quick example to explain itemRenderers (which it did very successfully), but I thought I would mention it.

    Thanks again,
    Ben

  5. Thanks for the catch Igor; no time to fix now, heading to MAX soon.

    Ben, that’s jacked, lol, I can duplicate that creation of the 4th column you are seeing! Weird.

  6. Hrm… using itemUpdated instead of setItemAt helps a little… at least, it fixes the duplicated items, but doesn’t resolve the sorting problem.

  7. Jesse, thanks for taking the time to put together the example. Good stuff. Reading the comments there’s some weirdness with it still, but I’m not surprised. If you had enough rows for the DG to scroll there’d be even more issues… Ick.

    Anyhow, after we talked yesterday I put together an example (which is very similar to yours) and in my event listener I used:

    var collectionIndex:Number = myAC.getItemIndex(myGrid.editedItemRenderer.data);
    myAC.setItemAt(myGrid.editedItemRenderer.data, collectionIndex);

    This works great if you selected and de-select the Checkbox controls slowly. Soon as you start clicking fast, Flex throws exceptions saying, I’m guessing, that the data propery of the myGrid.editedItemRenderer reference is undefined. Craziness.

    I’m going to change my example to be more like yours (using DataGridListData) and see if that fixes things.

    Thanks again man, you rock.

  8. Been playing around with your example Jesse and I’ve found all the code you have in the ‘isKnown’ case statement can be decreased to one line:

    my_ac.getItemAt(dgld.rowIndex-1).isKnown = event.target.selected;

    Not sure the impact this would have on the PersonVO Value Object though. It just seems weird to get the Array Collection item, cast it as a PersonVO, save the Checkbox selection to the PersonVO.isKnown property, AND update the Array Collection. Can you not just update the AC and it’ll do the rest?

  9. No, because the ArrayCollection has no way to know the that thing within it changed. Therefore, you have to use the setItemAt or itemUpdated methods so the ArrayCollection ‘knows’ that something within it changed, and it can then broadcast that change to everyone listening.

    The line you have above will set the value, yes, but will not update the DataGrid because he doesn’t know to redraw.

  10. I’ll have to put up edited versions of my example ’cause it’s working with just the one line of code w/o calling setItemAt or itemUpdated. To be sure it wasn’t a fluke (since I’m not using Value Objects) I tested the code in my examples and in your examples. Of course, I could totally be missing something, but the grid (the ‘view’) is updating correctly and the trace of the results in the Value Object are as well.

  11. I have to just be missing something really obvious here, but how do you construct/access an instance of DataGridListData if you’re not using a drop-in ItemRenderer. My checkbox needs to be centered, so its wrapped in a Canvas, which means listData is not available. Any help is greatly appreciated.

    Thanks,
    Ben

  12. I had the same problem when trying to wrap a VBox around my Checkbox MXML component. The error was related to ‘l istData’ being undefined. I’m living with uncentered Checkboxes for now.

  13. One thing to keep in mind when creating complex item renderers (ie where you use a canvas as the base component) is that it need to implemenet the IDropInListItemRenderer interface
    (implements=’mx.controls.listClasses.IDropInListItemRenderer’). Doing this will add in the pieces required for the datagrid to be able to set/get the listData property in the itemrenderer, which you need if you need info in the renderer about the column/row index or the datagrid. Without that you’re stuck. If you don’t implemenet that interface, the datagrid will never set the listdata because it does a type check on the item renderer when setting/getting listdata.

  14. perhaps it’s obvious, but that sort bug is extra bad because it will add/remove checkmarks as you keep clicking the column heading.

  15. After some investigation I’ve discovered that rowIndex on DataGridListData only refers to the item’s position in the DataGrid and is not related to the position in the dataProvider at all. To test this simply apply a filterFunction to your dataProvider and notice that the value of rowIndex will change for the same itemRenderer instance.

  16. So where is Adobe in all this, giving a nice clean example and explanation?

    I’m making a switch from the Microsoft/Java world and I’m surprised just how disorganized Adobe-Macromedia products are (at least from a documentation perspective). Its like living in the VB6 world of gotchas and lack of valuable technical information.

    Thank you for the examples. They’ll help a lot. Maybe I’ll figure the datagrid out now!

  17. I second the wish for the example and source code to be made available again.
    I’ve search a good deal and it looks like this example is the best match for what I’m trying to learn.

    Thanks in advance.

Comments are closed.