Some times you want to change the appearance of a data grid column or a cell at runtime. Maybe you want to react to a mouse click on a row/cell and you want to change the model behind as well as the UI presentation.
The single way to change the display of a list control (data grid, list, menu, and tree are all list controls) in Flex is to use item renderers. Each list component from Flex has a default renderer. For example, data grid has a default renderer called DataGridItemRenderer, which assumes that the data you want to display are text. When you want to display the data as something other than text, you need to create your own item renderer and then set the data grid to use your item renderer.
Item renderers act as a view for your data. And because they are not actually holding your data if your data grid displays 50 elements and you can see only 10 in the same time, it will create about 10 and reuse them as you scroll up and down. Reusing the item renderers is more efficient than creating all the item renderers for rows that are not in the current view.
The simplest way to create a custom item renderer for your data grid is inline. Using the tag mx:itemRenderer and than mx:Component you can declare any components from Flex you want. In order to get the data for the current row you use the “data” property. In the following example I create a custom renderer out of a VBox that hosts two other components: a label and a image. And to retrieve the “src” property for the current row I use this syntax: “data.src”.
In order to use a component as an item renderer and to be able to bind the “data” property to it, the component must implement this interface: mx.core.IDataRenderer. Most Flex components implement this interface and this is why my previous example worked. However, if you create your own UIComponent and you are not extending a Flex component you will need to implement the interface IDataRenderer.
Now, depending on your use case, you might want to:
- change the appearance of an entire column from your data grid
- change just one cell from your data grid
As usual I created a sample project. At the end of this article you can find a link for testing the code (you can right click on the page and choose view source from the contextual menu) and one for downloading the project.
Changing the appearance of an entire column
This is the easie of the two task. Suppose I want to change the appearance of the whole column when some one clicks on the data grid. First I will create two item renderers, one for each view of the column. Then I assign to the data grid the default item renderer for the column I want to customize. Next I attach an click item event listener on the data grid and inside of this event listener I switch the default item renderer with the second one. For fun I use a flag, to toggle the views. The interesting code is the event listener function. You don’t set directly the new item renderer to the column itemRenderer property. Instead, you set the item renderer that you want to be used wrapped in a ClassFactory object. This object it is used to generate instances of the given type with identical properties.
Changing the appearance of one cell
If you want to change just one cell, you can’t switch the renderers as this action will change the whole icon. Instead you can create your custom item renderer with different states, one for each different view you want. The default state will be the one you want to be displayed by the data grid when the data is loaded. To change the state for a given item renderer, you change the data displayed by the row. And in your renderer you evaluate the data to decide what view to display. Here is the code for item renderer:
Remember when I said that most of the Flex components implements IDataRenderer? By over riding the setter method, I am able to control what state I want to display.
The code that modifies the data model is inside of the event listener registered for the data grid item click event. It retrieves the data object from the item renderer, and because this object is of type Object, I can set dynamically a property. In this case, I add “showProgresBar” and I set to true. As the data provider is bindable and I just change one item, the set data method is called on my item renderer for each row from the current view. This gives me the opportunity to check the presence and the value of this flag and to switch the state.
The wrong way
You may be tempted to try another approach to change the appearance of a cell: to retrieve the item renderer of the cell you clicked on and directly inject into it new components. This is the wrong way to do it. For a instructional purposes, I included in an example along these lines in my project, and you can test it. In some cases will its seems to work, but remember that the data grid reuses the item renderers when you scroll down. So if you click on the first row, a progress bar is inserted in the second cell from the row, and as you start scrolling down, you will see other cells with the same progress bar (this is because of renderer reuse).