01 Sep 2010

Using getDefinitionByName() with External Library SWCs

2 Comments Flex/Flash, programing

In a recent project I was forced to dynamically generating UI Elements in flex from Strings. This is typically done using getDefinitionByName() as shown bellow. Although this works, in my app I never really know what the string is, nor do I know what the Class is named or where it is located. This becomes an issue since you must make reference to the Class somewhere in your code before it is available to the Flex framework.

This example shows the typical use of getDefinitionByName() with out any external SWC. Notice the imports and class references on the top of the Script block.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:controls="com.controls.*">
 
	<mx:Script>
		<![CDATA[
			import flash.utils.getDefinitionByName;
 
                       //You must import the classes and instantiate them
			import com.controls.TestControlA;TestControlA;
			import com.controls.TestControlB;TestControlB;
 
			private function loadTestClass(name:String):void
			{
			var ClassReference:Class = getDefinitionByName(name) as Class;
           		var s:DisplayObject = (new ClassReference() as DisplayObject)
           		testContainer.addChild(s);
			}
		]]>
	</mx:Script>
 
	<mx:VBox id="testContainer" />
 
	<mx:HBox id="buttonBar">
<!--You have to place the entire package location in the string-->
		<mx:Button label="Test A" click="loadTestClass('com.controls.TestControlA')" />
		<mx:Button label="Test B" click="loadTestClass('com.controls.TestControlB')" />
	</mx:HBox>
</mx:Application>

This won’t work since I need to make a reference to Classes that I won’t know the names of till run-time. My first step was to move a control into an external SWC, however I still am forced to make reference to the class so it becomes available, or I will get an error. This is a no go.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:controls="com.controls.*">
 
	<mx:Script>
		<![CDATA[
			import flash.utils.getDefinitionByName;
 
//You must import the classes and instantiate them
			import com.controls.TestControlA;TestControlA;
			import com.controls.TestControlB;TestControlB;
                        import com.controls.TestControlB;TestControlC; //Located in an External SWC
 
			private function loadTestClass(name:String):void
			{
			var ClassReference:Class = getDefinitionByName(name) as Class;
           		var s:DisplayObject = (new ClassReference() as DisplayObject)
           		testContainer.addChild(s);
			}
		]]>
	</mx:Script>
 
	<mx:VBox id="testContainer" />
 
	<mx:HBox id="buttonBar" >
                <!--You have to place the entire package location in the string-->
		<mx:Button label="Test A" click="loadTestClass('com.controls.TestControlA')" />
		<mx:Button label="Test B" click="loadTestClass('com.controls.TestControlB')" />
<mx:Button label="Test C" click="loadTestClass('com.controls.TestControlC')" />
	</mx:HBox>
</mx:Application>

The solution was actually pretty simple. If Flex is asking for a reference then why not just give it one. In the Library Project i create an additional Module file which i then loaded into my Shell application. Once the module is loaded then getDefinitionByName() works!

Shell Flex Application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:controls="com.controls.*">
 
	<mx:Script>
		<![CDATA[
			import flash.utils.getDefinitionByName;
			import com.controls.TestControlA;TestControlA;
			import com.controls.TestControlB;TestControlB;
			import com.controls.TestControlC;TestControlC;//Located in an External SWC
                       //NO REFEREANCE TO TestControlD
 
			private function loadTestClass(name:String):void
			{
				var ClassReference:Class = getDefinitionByName(name) as Class;
           		var s:DisplayObject = (new ClassReference() as DisplayObject)
           		testContainer.addChild(s);
			}
		]]>
	</mx:Script>
	<controls:ExternalClassModule creationComplete="buttonBar.visible=true" />
	<mx:VBox id="testContainer" />
	<mx:HBox id="buttonBar" visible="false">
		<mx:Button label="Test A" click="loadTestClass('com.controls.TestControlA')" />
		<mx:Button label="Test B" click="loadTestClass('com.controls.TestControlB')" />
		<mx:Button label="Test C" click="loadTestClass('com.controls.TestControlC')" />
		<mx:Button label="Test D" click="loadTestClass('com.controls.TestControlD')" />
	</mx:HBox>
 
</mx:Application>

Module in External Library Project

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Script>
		<![CDATA[
			import com.controls.TestControlD;TestControlD;
		]]>
	</mx:Script>
</mx:Module>


Popularity: 7% [?]

Tags: , ,
written by
I am a designer, developer & dad who interested in educational technology and using media for social goodness.
Related Posts

2 Responses to “Using getDefinitionByName() with External Library SWCs”

  1. Reply Rick Winscot says:

    Really… your just side-stepping the AS import with a MXML reference (see: xmlns:controls=”com.controls.*”). This is possible though…

    You’ll need to mark your dynamic components a Modules in the IDE – which compiles them to a .swf file. You can then load them with your preferred loader… and instantiate them dynamically without imports or MXML references.

    // where object is the .swf module you just loaded…
    var className:String = getQualifiedClassName(object);

    // instantiate the object
    var clazz:Class = getDefinitionByName(className) as Class;
    var target:Object = new ClassFactory(clazz).newInstance();

    …addChild( target as DisplayObject ). Done.

    • Reply Alex Britez says:

      I originally tried doing it that way, but must have done something wrong in processes. I am going to revisit this ASAP since your method is much less of a work around then mine.

Leave a Reply

Get Adobe Flash playerPlugin by wpburn.com wordpress themes