Search code examples
actionscript-3apache-flexdatagridflex4itemrenderer

How can I create a custom MXAdvancedDataGridItemRenderer in Flex4?


Well, I created one but it has a bunch of issues:

  • if I click in the rendered column I get an error:

TypeError: Error #1009: Cannot access a property or method of a null object reference. at Test/clickHandler()[C:\Documents and Settings\NDEGRAEV\workspace-dummy\Test\src\Test.mxml:27] at Test/___Test_AdvancedDataGrid1_click()[C:\Documents and Settings\NDEGRAEV\workspace-dummy\Test\src\Test.mxml:31]

  • the text is stuck to the top left corner of the cell;
  • the cell's background doesn't change to the selected one.

I'm new to Flex and I'm probably doing it completely wrong but here aren't many examples of custom MXAdvancedDataGridItemRenderer on the Net. Can you point me in the right direction?

Test.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               xmlns:test="*"
               initialize="init()">
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;

            [Bindable]
            private var data:ArrayCollection = new ArrayCollection();

            private function init():void {
                var dataItem:DataItem = new DataItem(1000, 1000);
                this.data.addItem(dataItem);
                dataItem = new DataItem(1001, 1001);
                this.data.addItem(dataItem);
            }

            private function clickHandler(e:Event):void {
                var dataItem:DataItem = e.currentTarget.selectedItem as DataItem;
                Alert.show(dataItem.col1 + ' ' + dataItem.col2);
            }
        ]]>
    </fx:Script>
    <mx:AdvancedDataGrid dataProvider="{data}" click="clickHandler(event);" x="0" y="0" designViewDataType="flat">
        <mx:columns>
            <mx:AdvancedDataGridColumn dataField="col1" headerText="Column 1"/>
            <mx:AdvancedDataGridColumn dataField="col2" headerText="Column 2" id="column2"/>
        </mx:columns>
        <mx:rendererProviders>
            <mx:AdvancedDataGridRendererProvider column="{column2}" renderer="MyRenderer" />
        </mx:rendererProviders>
    </mx:AdvancedDataGrid>
</s:Application>

MyRenderer.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                                  xmlns:s="library://ns.adobe.com/flex/spark" 
                                  xmlns:mx="library://ns.adobe.com/flex/mx" 
                                  focusEnabled="true">
    <s:Label id="lblData" />
    <fx:Declarations>
        <mx:NumberFormatter id="numberformatter" useThousandsSeparator="true" />
    </fx:Declarations>
    <fx:Script>
        <![CDATA[
            override public function set data(value:Object):void {
                if (value.col1 > 1000) {
                    lblData.text = numberformatter.format(value.col2);
                } else {
                    lblData.text = value.col2;
                }
            }
        ]]>
    </fx:Script>
</s:MXAdvancedDataGridItemRenderer>

Solution

  • I found a solution myself:

    <s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                                      xmlns:s="library://ns.adobe.com/flex/spark" 
                                      xmlns:mx="library://ns.adobe.com/flex/mx" 
                                      focusEnabled="true">
        <s:Label text="{format(this.row)}" width="100%" height="100%" verticalAlign="middle" paddingLeft="5"/>
        <fx:Declarations>
            <mx:NumberFormatter id="numberformatter" useThousandsSeparator="true" />
        </fx:Declarations>
        <fx:Script>
            <![CDATA[
                [Bindable]
                private var row:DataItem;
    
                override public function set data(value:Object):void {
                    this.row = value as DataItem;
                }
    
                override public function get data():Object {
                    return this.row
                }
    
                private function format(row:DataItem):Object {
                    if (row.col1 > 1000) {
                        return numberformatter.format(row.col2);
                    } else {
                        return row.col2;
                    }
                }
            ]]>
        </fx:Script>
    </s:MXAdvancedDataGridItemRenderer>