views:

3755

answers:

4

I have a DataGrid component that displays a few columns of data. It has one additional column that displays a Button that allows the user to take an action with regard to the record.

<mx:DataGrid dataProvider="{myData}">
    <mx:columns>
        <mx:DataGridColumn dataField="firstName" headerText="First Name" 
            width="75" />

        <mx:DataGridColumn dataField="LastName" headerText=" Last Name" 
            width="150" />

        <mx:DataGridColumn dataField="phone" headerText="Phone" 
            width="120" />

        <mx:DataGridColumn headerText="" width="110">
            <mx:itemRenderer>
                <mx:Component>
                    <mx:Box horizontalAlign="center" width="100%">
                        <mx:Button label="Take Action" />
                    </mx:Box>
                </mx:Component>
            </mx:itemRenderer>
        </mx:DataGridColumn>
    </mx:columns>
</mx:DataGrid>

I need to perform an action in the parent component, using other data that is available there, but unrelated to the data in the DataGrid.

What is the best way to catch the Button click in the parent component, and know what record it corresponds to?

Should I use a Custom Event, or an itemEditor, or something else completely?

+2  A: 

You need to make the itemRenderer a class, and then reference your DataGrid from within that class utilizing the methods described here. You can then dispatch events from the DataGrid, which are easy to listen for in the container that holds it. What you don't want to do is rely on bubbling or attempt to listen to the itemRenderer directly. You will probably want to create a custom event that carries the data property of the DataGrid row so that your event listener can quickly access this information.

Joel Hooks
+1  A: 

Thanks Joel. Here's the final solution I came up with after reading that article (which I've read before). I want to add the item whose Button was clicked to an Array which is a property of another item, so I pass the "other item" into the DataGrid Component as a property, and perform actions against it in the function call from the itemRenderer:

/* CustomDataGrid.mxml */
<mx:DataGrid xmlns:mx="http://www.adobe.com/2006/mxml"&gt;
    <mx:Script>
        <![CDATA[
            public var otherData:Object;

            public function takeAction(item:Object):void
            {
                otherData["children"][0] = item;
            }
        ]]>
    </mx:Script>

    <mx:columns>
        <mx:DataGridColumn dataField="firstName" headerText="First Name" 
            width="75" />

        <mx:DataGridColumn dataField="LastName" headerText=" Last Name" 
            width="150" />

        <mx:DataGridColumn dataField="phone" headerText="Phone" 
            width="120" />

        <mx:DataGridColumn headerText="" width="110" 
            itemRender="ActionButtonItemRenderer" />
    </mx:columns>
</mx:DataGrid>

/* ActionButtonItemRenderer.as */
package
{
    import flash.events.MouseEvent;

    import mx.controls.Button;

    public class ActionButtonItemRenderer extends Button
    {
        public function ActionButtonItemRenderer()
        {
            super();

            label = "Take Action";
        }

        override protected function clickHandler(event:MouseEvent):void
        {
            super.clickHandler(event);

            var owner:CustomDataGrid = listData.owner as CustomDataGrid;

            owner.takeAction(data);
        }
    }
}
Eric Belair
A: 

This solution works great; however, I have variable row heights and I cannot seem to be able to constrain the button sizes. Here is what I am trying:

package {

import customControls.CustomDataGrid;

import flash.events.MouseEvent;

import mx.controls.Button;

public class ActionButtonItemRenderer extends Button
{
    public function ActionButtonItemRenderer()
    {
        super();
        label = "Override";
        width = 80;
        height = 25;
        setStyle("fillAlphas", [1.0, 1.0]);
        setStyle("fillColors", ["#006699", "#006699"]);
        setStyle("color", "#FAFAFA");   
    }

    override protected function clickHandler(event:MouseEvent):void
    {
        super.clickHandler(event);

        var owner:CustomDataGrid = listData.owner as CustomDataGrid;

        owner.takeAction(data);
    }
}

}

The styles all set well as does the label. However, the height and width seem to be ignored. Any suggestions?

Michael
Try creating an itemRenderer that extends a Container component - Container, Box, etc. - and set the width and height on THAT, and make the Button a child of the Container. You may have to bubble the event again. If it gets too confusing, submit another question here on SO, and I'll try to help.
Eric Belair
A: 

ok, let's take this one more step. After the Data Grid is populated, I need to interrogate the dataProvider and based on the findings I need to change the button (disable it, set useHandCursor to false, etc.) How do I get a reference to the button so that I can work with it?

Michael