Link to home
Start Free TrialLog in
Avatar of hallikpapa
hallikpapa

asked on

Dynamically call components

I have a component called ServiceManage.mxml. It works great with the method listed. when I replace the word managePopUp with ServiceManage.

What I would like to do is dynamically call these pop up components as they are created. In the following example, managePopUp is being populated with the word "Test", and there is a Test.mxml, which is a duplicate of ServiceManage.mxml

On the var serviceWindow:managePopUp...... (I also tried it with a defined type of String instead of Class, but it gave me an error like it wanted it to be a class)

I get the following error:
Type was not found or was not a compile-time constant: managePopUp.      

Test.mxml is in the com folder. So the managePopUp var contains "com.Test", as a string though. Trying to make flex find that component...

Second question:
I am clicking on labels in the repeater index. Is it possible to make it so labels are only underlined and bolded if it finds a component that matches the name in managePopUp?


private function _servicePopUp(e:Event):void {
	//Pop up window for individual services. Component name must match service symbol name in DB
	var popUpName:ArrayCollection = new ArrayCollection( ArrayUtil.toArray( selectedUser.services ) );
	var managePopUp:Class = popUpName.getItemAt(e.currentTarget.repeaterIndex).serviceSymbol;
    var serviceWindow:managePopUp = 
        	managePopUp(PopUpManager.createPopUp(this, managePopUp, true));
 
    serviceWindow.bindGate = bindGate;
    var user:UserVO = UserVO(selectedUser);
    serviceWindow.user = user;
    PopUpManager.centerPopUp(serviceWindow); 
}

Open in new window

Avatar of Jones911
Jones911

try this:


var serviceWindow:this[managePopUp] =
                this[managePopUp](PopUpManager.createPopUp(this, this[managePopUp], true));
Avatar of hallikpapa

ASKER

Got these two errors on that line:

expecting semicolon before leftbracket.      
 this as not a valid type.      



managePopUp = "com.Test" --> (when created dynamically)
serviceWindow = com.Test (@43830a1) -->(when Test replaces managePopUp

That's the difference, so I need to do something to the value of managePopUp to convert it from a string to whatever flex needs it to be...
Try this one:

var serviceWindow:Class =
                this[managePopUp](PopUpManager.createPopUp(this, this[managePopUp], true));
I feel like a little progress is being made.

This is the current error:
 Implicit coercion of a value of type Class to an unrelated type mx.core:IFlexDisplayObject.

I changed the word Class to IFlexDisplayObject, and it bombed out on the serviceWindow.bindgate line & the serviceWindow.user line with an error:

Access of possibly undefined property bindGate through a reference with static type mx.core:IFlexDisplayObject.
Access of possibly undefined property user through a reference with static type mx.core:IFlexDisplayObject.



Hmm:

var serviceWindow:Sprite =
this[managePopUp](PopUpManager.createPopUp(this, this[managePopUp], true));
Got this error again:

Access of possibly undefined property bindGate through a reference with static type mx.core:IFlexDisplayObject.
Access of possibly undefined property user through a reference with static type mx.core:IFlexDisplayObject.

I must add that " Implicit coercion of a value of type Class to an unrelated type mx.core:IFlexDisplayObject." happened on the centerPopUp line...

I commented that out, and it compiled ok, but died when it got to the var serviceWindow:Class line with this error

ReferenceError: Error #1069: Property com.Test not found on com.users and there is no default value.


And there is most defintely a Test.mxml in the com folder.

Oops sorry, change the first two errors on the last comment to

Access of possibly undefined property users through a reference with static type flash.display:Sprite.
This is doable but I forgot how. Try

var serviceWindow:Class =
this[getDefinitionByName(managePopUp)](PopUpManager.createPopUp(this, this[getDefinitionByName(managePopUp)], true));
Cool. thanks for the effort. now.....

ReferenceError: Error #1065: Variable Test is not defined.
      at global/flash.utils::getDefinitionByName()
      at com::users/_servicePopUp()[Z:\src\com\users.mxml:122]
      at com::users/___users_Label7_click()[Z:\src\com\users.mxml:218]
just for testing try this:

var zzzTest:Test = new Test;
var serviceWindow:Class =
this[getDefinitionByName(managePopUp)](PopUpManager.createPopUp(this, this[getDefinitionByName(managePopUp)], true));
This is what my function looks like now, with this error:

ReferenceError: Error #1069: Property [class Test] not found on com.users and there is no default value.
      at com::users/_servicePopUp()[Z:\src\com\users.mxml:123]
      at com::users/___users_Label7_click()[Z:\src\com\users.mxml:219]


private function _servicePopUp(e:Event):void {
	//Pop up window for individual services. Component name must match service symbol name in DB
	var popUpName:ArrayCollection = new ArrayCollection( ArrayUtil.toArray( selectedUser.services ) );
	var managePopUp:String = "com." + popUpName.getItemAt(e.currentTarget.repeaterIndex).serviceSymbol;
 
    var zzzTest:Test = new Test;
	var serviceWindow:Class = 
		this[getDefinitionByName(managePopUp)](PopUpManager.createPopUp(this, 
			this[getDefinitionByName(managePopUp)], true));
    		
    serviceWindow.bindGate = bindGate;
    var user:UserVO = UserVO(selectedUser);
    serviceWindow.user = user;
    //PopUpManager.centerPopUp(serviceWindow); 
}

Open in new window

Can u try put the Text.mxml in the same folder then

var managePopUp:String = popUpName.getItemAt(e.currentTarget.repeaterIndex).serviceSymbol;
 
    var zzzTest:Test = new Test;
        var serviceWindow:Class =
                this[getDefinitionByName(managePopUp)](PopUpManager.createPopUp(this,
                        this[getDefinitionByName(managePopUp)], true));
I even tried just labeling it Test on top of dynamically grabbing it.

ReferenceError: Error #1065: Variable Test is not defined.
managePopUp = "Test";
    			var zzzTest:Test = new Test;
        		var serviceWindow:Class = 
                	this[getDefinitionByName(managePopUp)](PopUpManager.createPopUp(this, 
                        this[getDefinitionByName(managePopUp)], true));

Open in new window

OK I got it.  Here are 2 samples files

Sample 1 the test component.  Save it as TestComp
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" width="236" height="170">
	<mx:CheckBox x="187" y="96" label="Checkbox"/>
</mx:TitleWindow>

Open in new window

File 2

Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"  xmlns:ns1="*" creationComplete="init()">
	<mx:Script>
		<![CDATA[
			import mx.managers.PopUpManager;
			private var t:TestComp;
			
			private function init():void{
				var ClassName:String = 'TestComp';
				var dynObject:Class = getDefinitionByName(ClassName) as Class;
				var popUp:Object = dynObject(PopUpManager.createPopUp(this, dynObject, true));
			}
		]]>
	</mx:Script>
	
</mx:Application>

Open in new window

I remember why it didn't work they way you expect its because you need to declaire one instance of it or it never know show to reference that same component hence this line:

private var t:TestComp;

Its doing nothing but without it the example fails.  So for your example you would have to create one instance of every popup type at the top on the function.
Your example works perfectly, but somehow I cannot apply the same logic in my app? I still get that "Variable Test is not defined"

The Test.mxml is in the same folder as the component that calls this. I will continue to play around...




private var tt:Test;
...
...
...
 
var ClassName:String = 'Test';
                var dynObject:Class = getDefinitionByName(ClassName) as Class;
                var popUp:Object = dynObject(PopUpManager.createPopUp(this, dynObject, true));

Open in new window

Is the mxml component in the same folder?  You may need to import it.
yeah it's in the same folder ,and I imported it.....How odd
Is this at the top of the script block?

private var tt:Test;

Also did you clean the project.
Yeah private var tt:Test is with the rest of my class vars right after the imports at the top.

I just cleaned the project , and it's still giving me that error.
There is no other reference to it?  Can you post the full code?
here is the whole users.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" creationComplete="init()">
	<mx:Script>
		<![CDATA[
			import mx.utils.ObjectProxy;
			import mx.events.DataGridEvent;
			import mx.controls.Button;
			import mx.rpc.remoting.mxml.RemoteObject;
			import mx.rpc.events.ResultEvent;
            		import mx.rpc.events.FaultEvent;
			import mx.managers.PopUpManager;
			import mx.controls.Alert;
			import mx.utils.ArrayUtil;
			import mx.collections.ArrayCollection;
			import com.Test;
			
			[Bindable] private var selectedUser:UserVO;			
			
			[ArrayElementType("com.vo.UserVO")]			
			[Bindable] public var userList:ArrayCollection;
			
			
			[Bindable] public var oneUser:Object;
			[Bindable] public var gateway:String;
			protected var bindGate:Object;
			public var params:Object = {};
			private var tt:Test;
			
			
			[Bindable] public var conn:RemoteObject;
			
			private function init():void
			{
				activeUsers.label = "All Users";
			}
            
            		public function remoteConnect(gateway:String):void
			{
				conn = new RemoteObject;
				conn.source = "UserAcctService";
				conn.destination = "amfphp";
				conn.endpoint = gateway;
				conn.getUsers.showBusyCursor = true;
                conn.getUsers.addEventListener("result", getUsersResultHandler);
                conn.addEventListener("fault", _faultHandler);
                bindGate = conn;
                conn.getUsers();
            }
 
            public function getUsersResultHandler(event:ResultEvent):void {
                userList= new ArrayCollection(event.result as Array);
            }
            
            private function _getOneResult(event:ResultEvent):void {              
                selectedUser.services = event.result.services as Array;
            }
 
            private function _faultHandler (event:FaultEvent):void {
                Alert.show(event.fault.faultString, 'Error');
            }
 
			private function updateUser():void			
			{				
				var update:UserVO 		= new UserVO();
	 				update.id 			= selectedUser.id;
					update.firstName 	= txt_fname.text;
					update.lastName 	= txt_lname.text;
					update.email		= txt_email.text; 
					update.userActive 	= userActive.selected;
					update.userAdmin 	= userAdmin.selected;
				
					for(var i:String in selectedUser.services)
					{
						var services:ServiceVO 	= new ServiceVO();
						services.serviceID		= selectedUser.services[i].serviceID;
						services.serviceName	= selectedUser.services[i].serviceName;
						services.mappedName 	= userMappedName[i].text;
						services.mappedActive 	= serviceMappedActive[i].selected;
						update.services[i] 		= services;
					}
					 
				conn.saveUser.addEventListener("result", _getOneResult);
				conn.saveUser.addEventListener("fault", _faultHandler);
				conn.saveUser.showBusyCursor = true;
	            conn.saveUser(update);
			}
	
 
			private function _selectHandler( event:Event ):void
			{
				selectedUser = event.target.selectedItem as UserVO;
				if ( selectedUser != null )
				{
					conn.getOne.addEventListener("result", _getOneResult);
					conn.getOne.addEventListener("fault", _faultHandler);
                	conn.getOne(selectedUser.id);
				}
			}
 
			private function _newUser():void {
                var userWindow:NewUser = 
                    	NewUser(PopUpManager.createPopUp(this, NewUser, true));
                PopUpManager.centerPopUp(userWindow); 
                userWindow.bindGate = bindGate;
            }
            
            private function _servicePopUp(e:Event):void {
            	//Pop up window for individual services. Component name must match service symbol name in DB
            	
            	var popUpName:ArrayCollection = new ArrayCollection( ArrayUtil.toArray( selectedUser.services ) );
            	var managePopUp:String = popUpName.getItemAt(e.currentTarget.repeaterIndex).serviceSymbol;
 				
 				var ClassName:String = 'Test';
                var dynObject:Class = getDefinitionByName(ClassName) as Class;
                var popUp:Object = dynObject(PopUpManager.createPopUp(this, dynObject, true));
                		
                popUp.bindGate = bindGate;
                var user:UserVO = UserVO(selectedUser);
                popUp.user = user;
                //PopUpManager.centerPopUp(serviceWindow); 
            }
            
            private function _resetPassword():void {
            	var resetWindow:ResetPassword = 
               		ResetPassword(PopUpManager.createPopUp(this, ResetPassword, true));
                PopUpManager.centerPopUp(resetWindow); 
                resetWindow.loginName = selectedUser.userName;  
                resetWindow.bindGate = bindGate;     
            }
            
            private function _activeUsersChange(toggle:Boolean):void {
            	if(activeUsers.selected == true)
            	{
            		activeUsers.label = "Active Users";
            	}
            	else
            	{
            		activeUsers.label = "All Users";
            	}
            	conn.toggleUsers.addEventListener("result", getUsersResultHandler);
				conn.toggleUsers.addEventListener("fault", _faultHandler);
            	conn.toggleUsers(toggle);
            }
		]]>
	</mx:Script>
		<mx:HDividedBox width="100%" height="100%" label="Users">			
			<mx:Panel title="User Details"
				width="75%"
				height="75%"
				layout="vertical" cornerRadius="10">
									
				<mx:Form width="100%" height="100%" cornerRadius="10">
					<mx:FormHeading label=""/>
					
					<mx:FormItem label="User Name:" width="100%" direction="horizontal">
						<mx:Label text="{selectedUser.userName}"/>
					</mx:FormItem>
										
					<mx:FormItem label="" direction="horizontal">
						<mx:Label text="User Active:"/>
						<mx:CheckBox id="userActive" data="{selectedUser.userActive}"/>
						<mx:Label text="User Admin:"/>
						<mx:CheckBox id="userAdmin" data="{selectedUser.userAdmin}"/>
					</mx:FormItem>
						
					<mx:FormItem label="First Name:" width="75%" required="true">
						<mx:TextInput id="txt_fname"
							text="{ selectedUser.firstName }" width="75%"/>
					</mx:FormItem>
						
					<mx:FormItem label="Last Name:" width="75%" required="true">
						<mx:TextInput id="txt_lname"
							text="{ selectedUser.lastName }" width="75%"/>
					</mx:FormItem>
					
					<mx:FormItem label="Rank:" width="75%" required="true">
						<mx:TextInput id="txt_rank"
							text="{ selectedUser.userRank }" width="75%"/>
					</mx:FormItem>
						
					<mx:FormItem label="Email:" width="75%" required="true">
						<mx:TextInput id="txt_email"
							text="{ selectedUser.email }" width="75%"/>
					</mx:FormItem>
						
					<mx:FormItem label="Created At:" width="75%" required="false">
						<mx:Text id="txt_createdAt"
								text="{ selectedUser.createdAt }" width="75%"/>
					</mx:FormItem>
						
					<mx:FormItem label="Updated At:" width="75%" required="false">
						<mx:Text id="txt_updatedAt"
								text="{ selectedUser.updatedAt }" width="75%"/>
					</mx:FormItem>
					</mx:Form>
					<mx:Form>
					<mx:HRule width="391"/>
					
					<mx:FormItem direction="horizontal">
						<mx:Label width="150" text="Service Name" fontWeight="bold"/>
						<mx:Label width="150" text="Provider Specific Login" fontWeight="bold"/>
						<mx:Label width="175" text="Active" fontWeight="bold"/>
					</mx:FormItem>
					
					<mx:Repeater id="sp" dataProvider="{selectedUser.services}">					  
						<mx:FormItem direction="horizontal">
							<mx:Label width="150" click="_servicePopUp(event)" text="{sp.currentItem.serviceName}:" 
								textDecoration="underline" useHandCursor="true"/>							
							<mx:TextInput width="150" id="userMappedName" text="{ sp.currentItem.mappedName }"/>
							<mx:CheckBox width="175" id="serviceMappedActive" selected="{sp.currentItem.mappedActive}"/>
						</mx:FormItem>
		        	</mx:Repeater>
						
					<mx:FormItem label="" direction="horizontal" width="100%">
						<mx:Button label="Save"	click="updateUser()"/>
					</mx:FormItem>		
				</mx:Form>				
			</mx:Panel>
			
			<mx:Panel title="Users"
				width="75%"
				height="75%"
				layout="vertical" alpha="1.0">			
				<mx:DataGrid id="dg_users"
					width="100%"
					height="100%"
					change="_selectHandler( event )"
					dataProvider="{ userList }">			
					<mx:columns>
						<mx:DataGridColumn headerText="ID" dataField="id" width="50"/>
						<mx:DataGridColumn headerText="User Name" dataField="userName"/>
						<mx:DataGridColumn headerText="Last Name" dataField="lastName"/>
						<mx:DataGridColumn headerText="First Name" dataField="firstName"/>						
						<mx:DataGridColumn headerText="Email" dataField="email"/>
					</mx:columns>
				</mx:DataGrid>
				<mx:FormItem label="" direction="horizontal" width="100%">
					<mx:Button label="Refresh" click="conn.getUsers()"/>
					<mx:Button label="New User"	click="_newUser()"/>
					<mx:Button label="Reset Password" click="_resetPassword()"/>
					<mx:Button id="activeUsers"
            			label="{activeUsers.label}"
            			toggle="true"
            			click="_activeUsersChange(activeUsers.selected)"/>
				</mx:FormItem>
			</mx:Panel>
		</mx:HDividedBox>
	
</mx:VBox>

Open in new window

Put Text.mxml in the same folder and change the import to:

import Test;

And see.
ASKER CERTIFIED SOLUTION
Avatar of Jones911
Jones911

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Got an error "Definition Test could not be found"

Maddening isn't it.
aha! that className:String = 'com.Test' did it

Thank you so much! This was a doozy
Try change test to TestComp or something different incase there are some duplicates somewhere.

Did you try:

var ClassName:String = 'com.TestComp';

and leaving the Import as

import com.TestComp
Awsome!