2
votes

Weird issue with a Spark DataGrid:

  1. If there are an even number of data rows in the grid, everything is rendered just fine when the data changes in the grid.
  2. If there are an odd number of rows, up to a certain amount, the very middle row will not render correctly upon data changes.

In the code below, I set up an example of the issue and use an MX/Halo DataGrid (which works) and a Spark DataGrid (which does not work). Notice that column three in both grids has an item renderer of a spark button. The MX grid uses the same action script code that the spark grid does. The button in every row for both grids should be disabled when the status column of that particular row reads "Released".

The MX grid works just fine while for whatever reason, the spark grid on odd number of rows always has the middle row's button enabled while it should be disabled upon changing the status column. If there are an even amount of rows in the spark grid, it works just fine.

Here's the code example:

<?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"
               width="921" height="668" minWidth="955" minHeight="600"
               creationComplete="buildAnalytes(nsCount.value)">

    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;

            [Bindable]private var analytes:ArrayCollection;

            private function buildAnalytes(count:int):void {
                analytes = new ArrayCollection();

                for (var i:int = 0;i<count;i++) {
                    var analyte:Object = new Object();

                    analyte.analyte = "ANA" + (i+1);
                    analyte.result = i + 100;
                    analyte.status = "Pending";

                    analytes.addItem(analyte);
                }
            }

            private function release():void {
                var analyte:Object;

                for each (analyte in analytes) {
                    analyte.status = "Released";
                }

                analytes.refresh();
            }

        ]]>
    </fx:Script>

    <s:Panel id="panelResults" x="45" y="20" width="570" height="300" title="Results -- Halo (MX) DataGrid">
        <mx:DataGrid id="gridResultsMX" width="100%" editable="true" height="100%" dataProvider="{analytes}">
            <mx:columns>
                <mx:DataGridColumn width="100" dataField="analyte" headerText="Analyte" editable="false"/>
                <mx:DataGridColumn width="100" dataField="result" headerText="Result" editable="true"/>
                <mx:DataGridColumn width="100" dataField="comments" headerText="Comments" editable="false">
                    <mx:itemRenderer>
                        <fx:Component>
                            <mx:HBox width="100%" height="100%" horizontalAlign="center" verticalAlign="middle">
                                <s:Button width="90" height="15" label="Comments"
                                          enabled="{data.status != 'Released'}"
                                          />    
                            </mx:HBox>
                        </fx:Component>
                    </mx:itemRenderer>  
                </mx:DataGridColumn>

                <mx:DataGridColumn dataField="status" headerText="Status" editable="false"/>
            </mx:columns>
        </mx:DataGrid>
    </s:Panel>

    <s:Panel id="panelResults2" x="44" y="341" width="570" height="300" title="Results -- Spark DataGrid">
        <s:DataGrid id="gridResultsSpark" visible="true" x="0" y="0" width="100%"
                    height="100%" 
                    dataProvider="{analytes}" editable="true" fontSize="10">

            <s:columns>
                <s:ArrayList>
                    <s:GridColumn width="100" dataField="analyte" editable="false" headerText="Analyte"></s:GridColumn>
                    <s:GridColumn width="200" dataField="result" editable="true" headerText="Result"></s:GridColumn>

                    <s:GridColumn width="90" editable="false" headerText="Comments">
                        <s:itemRenderer>
                            <fx:Component>
                                <s:GridItemRenderer textAlign="center">
                                    <mx:HBox width="100%" height="100%" horizontalAlign="center" verticalAlign="middle">
                                        <s:Button width="70" height="15" label="Comments"
                                                  enabled="{data.status != 'Released'}"
                                                  />    
                                    </mx:HBox>
                                </s:GridItemRenderer>
                            </fx:Component>
                        </s:itemRenderer>                           
                    </s:GridColumn>

                    <s:GridColumn dataField="status" editable="false" headerText="Status"></s:GridColumn> 
                </s:ArrayList>
            </s:columns>
        </s:DataGrid>
    </s:Panel>

    <s:NumericStepper x="663" y="317" minimum="1" value="4" maximum="25" id="nsCount"/>
    <s:Button x="724" y="318" label="Build Analytes" click="buildAnalytes(nsCount.value)"/>

    <s:Button x="830" y="318" label="Release" click="release()"/>
</s:Application>

Has anyone else come across this? See anything in my code that might explain it?

Any help or thoughts would be appreciated. Oh, this is FlashBuilder 4.6, using 4.6 SDK.

2

2 Answers

0
votes

To avoid this problem, you can edit your release function like this :

...

private function release():void {

    var temp_analytes:ArrayCollection = new ArrayCollection();
    var obj:Object

    for each (var analyte:Object in analytes) {

        obj = {
            analyte : analyte.analyte,
            result : analyte.result,
            status : "Released" 
        }
        temp_analytes.addItem(obj);

    }

    analytes = temp_analytes;               
    analytes.refresh();

}

...

This code is 100% working for me (tested on Flex 4.5 and 4.6).

I hope that can help you.

0
votes

Don't forget to override set data function inside GridItemRenderer. Here you can change the property(enabled) of the component(Button) according to the data property(status). This fixes your issue. Now your GridColumn looks like below:

<s:GridColumn width="90" editable="false" headerText="Comments">
    <s:itemRenderer>
        <fx:Component>
            <s:GridItemRenderer textAlign="center">
                <mx:HBox width="100%" height="100%" horizontalAlign="center" verticalAlign="middle">
                     <fx:Script><![CDATA[
                         override public function set data(value:Object):void{
                            if(value){
                              super.data = value;
                              myButton.enabled = data.status != 'Released';
                            }
                         }
                      ]]></fx:Script>
                      <s:Button id = "myButton" width="70" height="15" label="Comments"/>
                </mx:HBox>
            </s:GridItemRenderer>
        </fx:Component>
    </s:itemRenderer>
</s:GridColumn>

Again why are you using <mx:HBox> instead of using <s:HGroup>?