Tuesday, April 22, 2008

Frustrating Flex problems solved #3 - DataGrid scrolling error

I'm currently working on a project that requires me to be using Flex 2 rather than Flex 3(I'm using an older version of Zinc, and avoiding upgrading if possible as we'll probably be moving to AIR after this project). But - issues in Flex 2 are no longer supported...

The problem i encountered was when changing the DataGridColumns and dataProvider of a DataGrid, it gave a #1010 error 'A term is undefined and has no properties.' when scrolling vertically.

After trawling the web for answers, I found a diamond here from Marc Sulinski, who suggested the hack of extending the DataGrid class and overriding updateDisplayList with the following:

override protected function updateDisplayList(w:Number, h:Number):void {
var b:Boolean = false;

if( rendererChanged ) b = true;

super.updateDisplayList(w, h);
if( b ) {
while( rowInfo.length > listItems.length ) rowInfo.pop();
}
}

Tuesday, April 1, 2008

ObjectCollection

i'd set up a repeater to display data returned from a ColdFusion call - which would either be a Y or N. I wanted to adjust how this appears to YES or NO, and thought a straightforward way of doing this would be set up an associative array:

[Bindable]
public static var yesNoTranslator:Object={N: "No",Y: "Yes"};


and my text component would look something like:

<text="{Constants.yesNoTranslator[repeater.currentItem.rsvpStatus]}">

Flex Builder produced warnings on this, however:
"Data binding will not be able to detect changes when using square bracket operator. For Array, please use ArrayCollection.getItemAt() instead."

Though in this case, i could ignore the warning and the app would work as desired, i could see that sometimes you may want your associative array to change and the binding wouldn't detect changes. Anyway, warnings are annoying to have hanging around, and for some strange reason they seem to propogate themselves in Flex Builder...

As the warning describes, if yesNoTranslator was an array, i could use ArrayCollection.getItemAt() instead. yesNoTranslator was an object and there is no equivalent with objects(for some reason), so i thought the simplest thing to do would be to create one, which i've called ObjectCollection:


package
{
import mx.utils.ObjectProxy;

public class ObjectCollection extends ObjectProxy
{
public function ObjectCollection(item:Object=null, uid:String=null, proxyDepth:int=-1)
{
super(item, uid, proxyDepth);
}
[Bindable(event="propertyChange")]
public function getItemAt(index:String):Object {
return(this[index]);
}
}
}


and modify my above code to:

[Bindable]
public var yesNoTranslator:ObjectCollection=new ObjectCollection({Y:"Yes",N:"No"});

< text="{yesNoTranslator.getItemAt(repeater.currentItem.rsvpStatus)}">