0
votes

I have the following code, with events associated to each element. When I click on the radio-button, the onItemClick event belongs to table is executing after onSelect event. I think that is due to table is the parent and rb2 the child.

private function onItemClick(e:ListEvent):void {
    selectedRow = parseInt(e.itemRenderer.data.Id)-1;
    trace("selectedRow: "+selectedRow);
}

public function selectPoint(event:MouseEvent):void{
    trace("selectPoint");
}

<mx:DataGrid id="table" dataProvider="{listCol}"
         itemClick="onItemClick(event)">
<mx:columns>
    <mx:DataGridColumn id="posibilidades" rendererIsEditor="true" 
                       editorDataField="selected" headerText="Posibilidades" width="100" textAlign="center"
                       draggable="false" editable="false" resizable="false" sortable="false">
        <mx:itemRenderer>
            <mx:Component>
                <mx:RadioButton name="rb2" label="Punto 2" fontSize="13" enabled="false" 
                                groupName="_rb" value="1" textAlign="center" 
                                preinitialize="event.target.styleName='rbstyle'"
                                click="outerDocument.selectPoint(event)"
                                creationComplete="outerDocument.rbCreated(event)"/>
            </mx:Component>
        </mx:itemRenderer>
    </mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>

I need to execute both events in reverse order: onItemClick, and then onSelect.

How can I execute onItemClick before onSelect? I read something about priorities associated to addEventListener, but it didn't work because events are for different components.

EDIT: I'll try to explain my problem and why I'm doing this weird stuff in Flex.

I've a Datagrid component which is updated dynamically by a button called "Add measure". This Datagrid have 4 columns; every measure added to this Datagrid have as a last cell (on 4th column) two radiobuttons.

|-----------------------------------------------------------------------------|
|            |             |             |                                    |
|  #1 cell   |   #2 cell   |   #3 cell   | (o) Radiobutton1  (o) Radiobutton2 |
|            |             |             |                                    |
|-----------------------------------------------------------------------------|

The problem is: when I remove a row, data is removed from display and works fine. But when I add a new one, radio-buttons are reused by Flex and I'm unable to know in which row the new radio-butons are (if Flex reuse them and I remove 3 rows and add a new one, the radio-buttons belongs to this new row can belongs to the last row removed, or another one; it's impossible to assure it).

So, I thought: "OK Fran, maybe you can add an event listener to itemClick in Datagrid, and when the user click on the radio-button, you can know in which row are the radio-button recently clicked (because of itemClick handler)". But Flex didn't execute the handlers in the order that I expected, so I'm really stuck right now.

I'm trying onRollOver event instead of onItemClick and works well, but not always.

3
It is considered bad practice to depend on event firing order, since it goes against the nature of asynchronous programming. I think you should consider a different approach. - RIAstar
Thanks, I supposed something like you wrote, but this should be in a synchronous mode :( - Fran Verona
You could do callLater(outerDocument.selectPoint, [event]) to defer the execution of the selectPoint method to the next render cycle, but I would strongly advise against it. Perhaps you should rather explain which behaviour you're trying to accomplish so we can help architecture this better. - RIAstar
Ok, I'm going to edit my own post =) - Fran Verona
OK, I get it now. Read this answer: stackoverflow.com/questions/8925474/…. It's a bit different from your situation, but the principle is the same. - RIAstar

3 Answers

0
votes

You could add both events a global Array in both event handlers (or use a single event handler). Check each time if the array size is of length 2, and contains a ListEvent and MouseEvent, and process the event objects using if(event is ListEvent), else....

Then clear the array, ready for the next events to be fired.

0
votes

Why don't you just keep one listener(onItemClick(e:Event)) on DataGrid and make use of 'currentTarget' and 'target' to identify like who caused the click and execute your sequence the way you want it. In this case, target.id would be 'rb2' and currentTarget.id would be 'tabe'.

    protected function onItemClick(event:Event):void
    {
        //handle your table click here.
        selectedRow = parseInt(event.itemRenderer.data.Id)-1;
        if(event.target.id == 'rb2')
        {
            //do something
        }
    }

Hope it helps.

0
votes

If the problem is to identify the current row when flex recycles the itemrenders, we can do with one eventlistener inside the itemRenderer. Create a new CustomItemRender class which extends uiComponent and implementing IDropInListItemRenderer and IListItemRenderer. Access the row information and the data information using listdata and data properties.

For example CustomRenderer code is as below:

package { import flash.events.MouseEvent;

import mx.controls.DataGrid;
import mx.controls.RadioButton;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.UIComponent;

public class CustomItemRender extends UIComponent implements IDropInListItemRenderer,IListItemRenderer
{
    public function CustomItemRender()
    {
        super();
    }


    private var _data:Object
    public function get data():Object
    {
        return _data;
    }

    public function set data(value:Object):void
    {
        _data = value;
    }

    private var _listData:BaseListData
    public function get listData():BaseListData
    {
        return _listData;
    }

    public function set listData(value:BaseListData):void
    {
        _listData = value;
    }

    private var radioButton:RadioButton;
    override protected function createChildren():void {
        super.createChildren();
        if(!radioButton){
            radioButton = new RadioButton();
            radioButton.addEventListener(MouseEvent.CLICK, handleRadioButtonClick, false, 0, true);
            this.addChild(radioButton);
        }           
    }

    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        radioButton.move(10, unscaledHeight*0.5);
    }

    private function handleRadioButtonClick(event:MouseEvent):void{
        trace("row data: "+data);
        trace("currently visible row Info: "+listData.rowIndex+" "+listData.columnIndex);
        trace("dataprovider "+DataGrid(listData.owner).dataProvider.toString())
    }
}

}

This example does not solve your problem. I hope this would help you.