Flex Tip: How to get all items (ignoring the filter) in an ArrayCollection

If you have an ArrayCollection with a filter function set and you loop through the items, you’ll only see the items which match the filter. The catch is sometimes you want to see them all. Initially I was doing the following.

var filterFunction:Function = arrayCollection.filterFunction;
arrayCollection.filterFunction = null;
arrayCollection.refresh();
			
for each (var obj:Object in arrayCollection)
{
	// do stuff
}
			
arrayCollection.filterFunction = filterFunction;
arrayCollection.refresh();

This worked but was pretty ugly. Here’s a nicer approach:

for each (var obj:Object in arrayCollection.source)
{
	// do stuff
}

What I keep finding in Flex is that I’m able to come up with complex code to solve simple problems but when I revisit it months later there’s usually a more straight-forward solution.

Hope this helps,
Hillel

Flex DataGrid: Click once to select, click twice to edit

In the application I’m working on there’s a datagrid which when the user selects a row we update the info on the side page. The catch was we also enabled editing in the datagrid. It was strange to click the row to see the details on the side and then immediately be in edit mode.

Initially we required that the user double-click a field to edit it. The solution was based on the comment provided by Jana in this post.

The concern was that a user may not realize that you needed to double-click to edit the field. In the code provided below the user can select a row by clicking it. If they then click a field in the selected row it will switch in to edit mode.

<?xml version="1.0" encoding="utf-8"?>
<mx:DataGrid xmlns:mx="http://www.adobe.com/2006/mxml">
	
	<mx:Script>
		<!&#91;CDATA&#91;
			import mx.controls.listClasses.IListItemRenderer;
			import mx.events.ListEvent;
			
			private var _selectedRow:int = -1;
			private var _clickCount:uint;
			
			override protected function mouseUpHandler( event:MouseEvent ):void 
			{
				editable = (_clickCount == 2);
				
				super.mouseUpHandler( event );													
			}
			
			override protected function selectItem( item:IListItemRenderer, shiftKey:Boolean, ctrlKey:Boolean, transition:Boolean=true ):Boolean
			{
				var returnValue:Boolean = super.selectItem( item, shiftKey, ctrlKey, transition );
				
				if (selectedIndex == _selectedRow)
				{
					_clickCount = 2;
				}
				else
				{
					_selectedRow = selectedIndex;
					_clickCount = 1;
				}
				
				return returnValue;			
			}
			
		&#93;&#93;>
	</mx:Script>

</mx:DataGrid>

Hope you find this helpful,
Hillel

Problem with data binding in Flex

This issue took me a while to figure out. It looks like errors inside function used for data binding aren’t reported to the Flash debug player. Take this code as an example.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	
	<mx:Script>
		<!&#91;CDATA&#91;
			
			private var _isValid:Boolean
			private var _myString:String;
			
			&#91;Bindable&#93;
			private function get isValid():Boolean
			{
				return _myString.length > 0;
			}
			
			private function set isValid( value:Boolean ):void
			{
				_isValid = value
			}	
		
		&#93;&#93;>
	</mx:Script>
	
	<mx:HBox width="100" height="100" 
		backgroundColor="{ isValid ? 0xFF0000 : 0x00FF00 }"/>
	
</mx:Application>

Based on the code you’d expect the background color to be either red or green. But if you run this the background color doesn’t get set at all. The reason is there’s an error inside ‘get isValid’, since _myString is null checking the value for length fails.

What makes this sort of problem really hard to track down is the compiler doesn’t generate an error when the call to determine the string’s length fails.

Hope this helps,
Hillel

How to get the real location of a point in Flex

When you create a point within a component the Flash player uses the component’s coordinate space. So for example, if your custom component is 200 pixels from the top of the screen and you create a point within it. If you set the point to a Y value of 0 it will be at the top of the component (which means it will be 200 pixels from the top).

Originally I had written a helper class which would recurse its way up the display chain and total up all the values of the X’s and Y’s, but there’s a far simpler way to get the point’s real location.

You can use the localToGlobal function to translate a point’s coordinate space. For more information check out the Adobe docs

Best,
Hillel

Flex Tip: Remove/delete item from an array

Updated March 10th, 2009
It turns out this is probably not the best way to do it. As per the comments below, be careful using the delete command as it will only set the element to undefined (the length of the array won’t be shortened. I considered deleting this post, but I think it may still be useful in that it helps clarify the difference between slice and delete.

Original post starts here…

If you search for this topic you’ll find that this can be accomplished using the splice function.

MyArray.splice(3, 1);

This was how I was doing it for a while, but I just recently discovered a simpler method.

delete MyArray[3]

Hope this helps,
Hillel

Flex Tip: Error accessing the stage when the app first loads

Long story short use the applicationComplete event.

This is something I struggled with for a while. I don’t use a mouse much and like to code keyboard shortcuts into the applications I build. My code initially looked like this:



Flex Tip: Check if string starts with…

I wrote a post a while back discussing how to optimize searching in Flex. I’ve noticed that people keep finding the post by searching for ‘flex string starts with’. The problem is the post doesn’t actually answer that question.

So… here’s how to do it:

public static function startsWith( string:String, pattern:String):Boolean
{
	string  = string.toLowerCase();
	pattern = pattern.toLowerCase();
			
	return pattern == string.substr( 0, pattern.length );
}

Since we’re talking about string searching I may as well throw out one more quick tip. The above code will match ‘ma’ in ‘Mary’ but let’s say the name is ‘Mary Anne’. Here’s how to match ‘ma’ or ‘an’.

public static function isMatch( string:String, pattern:String ):Boolean
{
	if (startsWith( string, pattern ))
	{
		return true;
	}
			
	var words:Array = string.split( " " );
			
	for each (var word:String in words)
	{
		if (startsWith( word, pattern ))
		{
			return true;
		}
	}
			
	return false;
}

One quick note, in the above code we search the full string first before searching each of the words. We’re doing this to make sure (using the last example of ‘Marry Ane’) that the function also matches ‘mary a’.

Best,
Hillel