Accessibility
 

Understanding Flex itemRenderers – Part 3: Communication


Table of Contents

Comments

Events

In the previous articles I showed how to use event bubbling to let the itemRenderer communicate with the rest of the application. I think this is certainly quick. But I also think there is a better way, one which fits the assumption that an itemRenderer's job is to present data and the control's job is to handle the data.

The idea of the MyTileList control is that it is the visible view—of the catalog of books for sale. When a user picks a book and wants to buy it, it should be the responsibility of the list control to communicate that information to the application. In other words:

<CatalogList bookBuy="addToCart(event)" />

The way things are set up right now, the event bubbles up and bypasses the MyTileList. The bubbling approach doesn't assoicate the event (bookBuy) with the list control (MyTileList), allowing you to move the control to other parts of your application. For instance, if you code the event listener for bookBuy on the main Application, you won't be able to move the list control to another part of the application. You'll have to move that event handler, too. If, on the other hand, you have the event associated with the control, you just move the control.

Look at it this way: suppose the click event on the Button wasn't actually an event dispatched by the Button, but bubbled up from something inside of the button. You'd never be able to do: <mx:Button click="doLogin()" label="Log in" />; you would have to put the doLogin() function someplace else, and that would make the application even harder to use.

I hope I've convinced you, so here's how to change the example from bubbling to dispatching from the list control.

  1. Add metadata to the CatalogList control to let the compiler know the control dispatches the event:
    import events.BuyBookEvent;
    	import mx.controls.TileList;
    
    	[Event(name="buyBook",type="events.BuyBookEvent")]
    	
    	public class CatalogList extends TileList
    	{
  2. Add a function to CatalogList to dispatch the event. This function will be called by the itemRenderer instances:
    public function dispatchBuyEvent( item:Object ) : void
    		{
    			var event:BuyBookEvent = new BuyBookEvent();
    			event.bookData = item;
    			dispatchEvent( event );
    		}
    		
    	}
  3. Change the Buy button code in the itemRenderer to invoke the function:
    <mx:Button label="Buy" fillColors="[0x99ff99,0x99ff99]">
        <mx:click>
        <![CDATA[
            (listData.owner as CatalogList).dispatchBuyEvent(data);
        ]]>
        </mx:click>
        </mx:Button>

Now the Button in the itemRenderer can simply invoke a function in the list control with the data for the record (or anything else that is appropriate for the action) and pass the responsibility of interfacing with the rest of the application onto the list control.

The list control in this example dispatches an event with the data. The application can add event listeners for this event either using ActionScript or, because of the [Event] metadata in the CatalogList.as file, MXML; using [Event] metadata makes it easier for developers to use your code.

Where to go from here

itemRenderers should communicate any actions using events. Custom events allow you to pass information with the event so the consumer of the event doesn't have to reach out to the itemRenderer for any data.

itemRenderers should "react" to changes in data by overriding their set data functions. Inside of the function they can access values in their listData.owner. They could also access data stored in a static class or in the main application via Application.application.

In the next article we'll look at incorporating states into itemRenders.