Skipping id in MXML to create private sub-components

As you probably know, when you create an MXML component in Flex, and you give one of its children an id, that child will become a public property on the class. What if you’d rather make it private because you don’t want code outside the MXML component accessing sub-components? Well, you could do something like this:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
	creationComplete="application_creationCompleteHandler(event)">

	<mx:Button label="Example" preinitialize="_exampleButton = Button(event.currentTarget)"/>

	<mx:Script><![CDATA[
		import mx.events.FlexEvent;
		import mx.controls.Button;

		[Bindable]
		private var _exampleButton:Button;

		private function application_creationCompleteHandler(event:FlexEvent):void
		{
			trace("_exampleButton:", this._exampleButton);
		}

	]]></mx:Script>
</mx:Application>

In the code above, there’s a private _exampleButton variable that will be used to reference the Button we create in the MXML without an id property. It is Bindable so that we can use its properties in binding elsewhere. Hooking onto the FlexEvent.PREINITIALIZE event, we pass the component reference to the variable using the currentTarget property of the event.

If you have a reason to enforce stronger encapsulation in MXML components, this method could be useful, but it’s probably overkill most of the time. Obviously, this won’t stop someone from using standard display list functions to access the child you “hid” by making it private. I doubt I’ll use this anywhere, but it was a fun exercise, and I thought I’d share.

A Couple Related Links

About Josh Tynjala

Josh Tynjala is a frontend developer, open source contributor, bowler hat enthusiast, and karaoke addict. You might be familiar with his project, Feathers UI, an open source user interface library for Starling Framework that is included in the Adobe Gaming SDK.

Discussion

  1. Matt Garland

    I could see use cases for this, but after spending a week with JQuery, I’d rather go the opposite direction: Flex need more DOM-like functionality for the view. I’d like to grab types of objects more easily, either by id, partial id, class, etc. And I’d like the ability to step down the display hierarchy without worrying about enclosing objects with no or different ids. Give me this power and I will not abuse it, promise. I spend too much time collecting and accessing object references.

  2. Josh Tynjala

    Hi Matt, it’s not the same as JQuery, but I created something I called DisplayQuery (name similarities unintentional) for AS3. It’s actually very much like E4X, but it’s for the display list instead of XML. Here’s an example of how it works:

    var dq:DisplayQuery = new DisplayQuery(this);
    //getChildByName() with @
    var grandChild:Sprite = dq.@childName.@grandChildName.toDisplayObject();
    
    //or
    
    //descendants operator
    grandChild = dq..@grandChildName.toDisplayObject();

    I haven’t released it yet, but the code is floating around on my Google Code account: org.josht.dq.*. The classes work as closely to XML and XMLList as I could make them.

    In the future, I may add support for CSS-style selectors, in addition to the @ and .. operators. I have a proof of concept where the code looks something like this:

    var tf:TextField = dq..$["Sprite>TextField"];
  3. Andy Gorman

    I think this is a very useful flex idiom. It may not be bullet proof, but I do feel better making an effort to increase encapsulation.

  4. Alan G.

    Nice solution. Was SDK-219 ever addressed (its been around since 2007, wow)? Is there a cleaner way to achieve this now? This is clearly a problem from the standpoint of proper encapsulation.