Acting on a "close-window" event for PopUpManager TitleWindow

I have two mxml files:

My main mxml file has a feature that pops up a TitleWindow for user input.  When the appropriate input is made in that TitleWindow popup, it fills a bindable ArrayCollection that facilitates populating a ComboBox in the main mxml file.  The TitleWindow then removes itself (via a call to PopUpManager.removePopUp(this)) and I'm back at my main mxml file where the ComboBox is showing the expected entries.  So far so good.

When the user selects from the main's ComboBox, the "changed" event will trigger a database call and fill a DataGrid with the applicable contents.  Again... so far so good.

Here's my problem (and it's quite beginner-level, I'm sure)...  After the PopUpManager removes itself, the DataGrid is empty because the ComboBox hasn't been triggered yet by a 'changed' event.  I would like to populate the DataGrid after the TitleWindow is removed, to reflect the first option (selectedIndex=0) in the ComboBox.  I don't know how to hook into that close event for the TitleWindow from my main.mxml file.
stockblocksAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Siva Prasanna KumarPrincipal Solutions ArchitectCommented:
I think the simplest thing to do is to reset/reassign the Data Grids dataProvider before removing the Titlewindow.

I think u can also try triggering the change event manually but I feel its not needed as the above way should fix it. Just check and let me know.

0
stockblocksAuthor Commented:
I can't see how the DataGrid's provider has anything to do with my question. Perhaps I failed to convey the whole picture of my project...  here it is in more detail:  

* The PopupManager is a password-entry dialog of sorts.  When my Flex app loads, it immediately passes control to that popup.  I like how Flex blurs the main window while the popup dialog is showing.  I offer no cancel button.

* I have two ArrayCollections:  one feeds the Combobox with user-specific options, and the other feeds the DataGrid but is triggered only when there is a "change" event in the Combobox.

* The user must enter a valid login, at which point the ComboBox on the main screen (through the first ArrayCollection) will populate with options unique to that user.  But a database query in order to fill the second ArrayCollection (for the DataGrid) has yet to be triggered because the ComboBox hasn't been interacted with yet.  So after the popup disappears, the ComboBox is accurately showing all the user-specific options. But the DataGrid is initially empty. Sure, it fills up with data after I click various options in the ComboBox.  But I would like the DataGrid to display something the instant someone "logs in".  I need another hook besides the Combobox's "change" event.

0
julianopolitoCommented:
{//Here is the function the closes the window. It also will dispatch event for the combo so your listeners for the combo also triggers and populate the grid with the first option
PopUpManager.removePopUp(this);//removes popup
mycombo.selectedIndex = 0;//selects first item
//dispatches event as user had done so
mycombo.dispatchEvent(new ListEvent("change",false,false,0,0,null,null));
 }
0
Powerful Yet Easy-to-Use Network Monitoring

Identify excessive bandwidth utilization or unexpected application traffic with SolarWinds Bandwidth Analyzer Pack.

stockblocksAuthor Commented:
The problem there is that I can't address the ComboBox from my popup dialog.   The ComboBox is declared in the main.mxml file.

Summary of my amazing Flex project...

1) main.mxml: hosts the two ArrayCollections. One is a dataprovider for the DataGrid, and the other for the ComboBox.  The ArrayCollection for the ComboBox is associated with (i.e., "pointed to", I don't know the proper Flex terminology) a bindable ArrayCollection in the popup dialog.

2) userentry.mxml (i.e., the "popup dialog"): has one bindable ArrayCollection that "points to" the instantiated ArrayCollection in main.mxml.  It's put here so that I can immediately fill in data specific to the user's name when s/he "logs in".  That action thru binding will populate the Combobox options in main.mxml.

In my main.mxml file, I have an HTTPService that can be called at any time.  I currently have it set on the ComboBox's change event.   I could easily call it at any additional location... specifically I'd like to trigger it when the popup dialog is removed.  I don't know the Flex 'hook' to make that happen.
0
julianopolitoCommented:
Here it is. I made two files. A popup component and an application. I used Application.application static reference to the application to talk between them. take a look:

//eexchange.mxml application
<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
	xmlns:mx="http://www.adobe.com/2006/mxml" 
	layout="vertical" creationComplete="init()">
	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.core.IFlexDisplayObject;
			import mx.containers.TitleWindow;
			import mx.managers.PopUpManager;
			[Bindable]
			public var users:ArrayCollection = new ArrayCollection();
			
			private function init():void{
				var pop:TitleWindow = TitleWindow(PopUpManager.createPopUp(this,userentry,true)); 
			}
		]]>
	</mx:Script>
	
	<mx:TextInput id="userT" />
	<mx:TextInput id="pwdT" />
	<mx:ComboBox id="myCombo" dataProvider="{users}" />
</mx:Application>
 
 
//userentry.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow 
	xmlns:mx="http://www.adobe.com/2006/mxml" 
	layout="vertical" width="300" height="206" 
	verticalAlign="middle" horizontalAlign="center" 
	title="User info">
	<mx:Script>
		<![CDATA[
			import mx.core.Application;
			import mx.managers.PopUpManager;
			private function close():void{
				PopUpManager.removePopUp(this);
				Application.application.userT.text = userText.text;
				Application.application.pwdT.text = pwdText.text;
				Application.application.users.addItem(userText.text);
			}
		]]>
	</mx:Script>
	
	<mx:Form>
		<mx:FormHeading label="User Info"/>
		<mx:FormItem label="user">
			<mx:TextInput id="userText"/>
		</mx:FormItem>
		<mx:FormItem label="pwd">
			<mx:TextInput id="pwdText"/>
		</mx:FormItem>
	</mx:Form>
	<mx:Button label="OK" click="close()"/>
	
</mx:TitleWindow>

Open in new window

0
julianopolitoCommented:
there is also another way, customizing the title window component with an event. I'll make an example and send in a while.
0
julianopolitoCommented:
here I'm again. This solution is much better than that one above. Though it requires more knowledge, and more design. I made it fast so don't bother with the design of the solution, it's not the best best, but you can improve it. Now we have 3 files: the application, the component and a custom event class. When you create the popup , get the reference to it, and add an event listener for the custom event "closepopup". The "closepopup" will be dispatched from the component, and this event class MyClosePopupEvent, has a property data typed object so you can put whatever you want there. I put the username and password from the form on the popup. Take a look at the files. I'll zip but you need to change the extension to .zip .
eexchange.zip.pdf
0
stockblocksAuthor Commented:
Wow.  This looks promising!

In your userentry.mxml file, you have the following:

   private function close():void{
      PopUpManager.removePopUp(this);
      dispatchEvent(new MyClosePopupEvent({user:userText.text, pwd:pwdText.text}));
   }

I had a similar function (called 'removeMe()'), which only had the removePopUp(this) call.  I don't need the 'user' and 'pwd' data passed, so I converted the code to the following...

   private function removeMe():void {
      PopUpManager.removePopUp(this);
      dispatchEvent( new MyClosePopupEvent() );     <--- ERROR HERE
   }

I'm unfamiliar with event class creation in Flex.  Perhaps that's why I got the above error flagged, but moving on...  

  ...back in my main program, I have adapted your 'onClose' function to be as follows...

   private function onClose(e:MyClosePopupEvent):void{
      // The username has already been populated in a bindable text field, thanks to
      // our popup user entry dialog. Now let's grab ALL data for this user.  
      // This mimmicks the action of clicking the topmost item in the pulldown.
      userSpecificDataLister.send();  
   }

Anyway, after making the above change in removeMe(), Flex stops at where I've labeled "ERROR HERE" above with the following msg:

"1136: Incorrect number of arguments. Expected 1."

I'm scratching my head now, since there IS only one argument in the call to dispatchEvent.  I thought I'd pass this by you just in case I can't figure out how to fix it.

0
julianopolitoCommented:
That's because MyClosePopupEvent class constructor needs at least 1 argument. If you don't need passing data through it (as I thought you needed) it's even simpler. You don't need the custom event class, you just need to know when the popup closes ? Well, anyway, let's just leave it that way and make a little change to the MyClosePopupEvent. Open the file, and change the constructor like this.... no wait, I'll send you the files again. As you told me you do not need the data from the event I'll change the example so you don't need the custo event ok?

So now I'm just dispatching a simple Event.CLOSE from the component. Forget about the custom event if you don't need extra information coming from the event object - but take care with the design of your components. Try not to bind internal properties of the component to properties of the application directly, cause you may have some problems if you need to update something.


eexchange.zip.pdf
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
stockblocksAuthor Commented:
With your help, I think I'm almost there.  The code you provided makes sense to me (and yes, all I ever needed was a trigger on the dialog close event).   When I implemented the code samples you provided, I get the following error response (ref: the first line states "cannot convert flash.events... to mx.events.CloseEvent").   Anything I'm doing wrong?

TypeError: Error #1034: Type Coercion failed: cannot convert flash.events::Event@b926499 to mx.events.CloseEvent.
      at flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunction()
      at flash.events::EventDispatcher/dispatchEvent()
      at mx.core::UIComponent/dispatchEvent()
      at PasswordDialog/::removeMe()
      at PasswordDialog/::populateUserPulldown()
      at PasswordDialog/__userMenuPopulator_result()
      at flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunction()
      at flash.events::EventDispatcher/dispatchEvent()
      at mx.rpc.http.mxml::HTTPService/http://www.adobe.com/2006/flex/mx/internal::dispatchRpcEvent()
      at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::resultHandler()
      at mx.rpc::Responder/result()
      at mx.rpc::AsyncRequest/acknowledge()
      at ::DirectHTTPMessageResponder/completeHandler()
      at flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunction()
      at flash.events::EventDispatcher/dispatchEvent()
      at flash.net::URLLoader/flash.net:URLLoader::onComplete()
0
julianopolitoCommented:
you must be trying to implement the listener function with CloseEvent like:

function onClose(e:CloseEvent):void{}

but the event I used was Event (don't confuse Event.CLOSE with CloseEvent, ok?)
so it should be like this

function onClose(e:Event):void{}

Can you check it out?
0
stockblocksAuthor Commented:
Yup.  That's what I did.  Here's the snippet from my file...
        .
        .
        .
       userLogin.addEventListener(Event.CLOSE,onClose);
               
       PopUpManager.centerPopUp(userLogin);      
        }
                        
       private function onClose(e:Event):void{
        // trace("window closed");
         userSpecificDataLister.send();  
       }
        .
        .
        .

And here's the code from my popup file...

            private function removeMe():void {
              PopUpManager.removePopUp(this);
              dispatchEvent(new Event(Event.CLOSE));
            }

...which also has the following above the <mx:Script> line:

      <mx:Metadata>
            [Event("close")]
      </mx:Metadata>

0
julianopolitoCommented:
When does it happen? When you click the button?
I need to see the whole code , cause it seems the problem is somewhere else.
Who calls removeMe? A button?
0
stockblocksAuthor Commented:
removeMe() is called from a routine that's triggered by the Submit button's click event.

Could it be something so simple as not including an appropriate 'import' line?

0
julianopolitoCommented:
not likely. You need to verify where this error is happening. What is going on is that somewhere you added a listener with type Event where it should be CloseEvent. Are you shure that in the TitleWindow tag you did not put something like: close="removeMe(event)" ?? That is the only thing I can think. If it is not, send the mxml for the app and titlewindow.
0
stockblocksAuthor Commented:
You say...

"somewhere you added a listener with type Event where it should be CloseEvent"

In the revised code you provided:

In userentry.mxml...
                  private function close():void{
                        PopUpManager.removePopUp(this);
                        dispatchEvent(new Event(Event.CLOSE));
                  }

And in eexchange.mxml...

                  private function init():void{
                        var pop:userentry = userentry(PopUpManager.createPopUp(this,userentry,true));
                        pop.addEventListener(Event.CLOSE,onClose);                        
                  }

I see no reference to "CloseEvent" in your code.  Did you mean the other way around?
0
stockblocksAuthor Commented:
Here's my removeMe() routine...

            private function removeMe():void {
              Alert.show( "before call to dispatchEvent()" );
              dispatchEvent(new Event(Event.CLOSE));
              Alert.show( "after call to dispatchEvent()" );
              PopUpManager.removePopUp(this);
            }

The error mentioned in yesterday's posting is happening when I click the Submit button in the popup, which calls removeMe().  The error occurs with the call to dispatchEvent(new Event(Event.CLOSE));.

0
stockblocksAuthor Commented:
UPDATE...   In a recent posting, you stated...

"Are you shure that in the TitleWindow tag you did not put something like: close="removeMe(event)" ?? That is the only thing I can think."

The answer is, YES I was doing that, as shown here...
mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
        showCloseButton="false"
        width="358" borderAlpha="0.9"
        close="removeMe();"
       height="202" verticalScrollPolicy="off" horizontalScrollPolicy="off">

       <mx:Metadata>
            [Event("close")]
      </mx:Metadata>


So I removed close="removeMe();" and the error no longer occurs when the Submit button is clicked.  But the datagrid in the main window isn't populated either.  It's like I'm back to ground zero.  The onClose(e:Event) in my main mxml file isn't being called (the trace("window closed") doesn't show).

0
stockblocksAuthor Commented:
I took your code and compiled/ran it, and it works perfectly.  So rather than pull you into some off-the-beaten-path venture to find some other oversight in my code, I figured I'd Accept your final code contribution as the solution.  It is just what I was looking for, as I stated in my opening posting on this thread.

Thanks again!

SB
0
julianopolitoCommented:
very odd. Change the metadata


       <mx:Metadata>
            [Event("closepopup")]
      </mx:Metadata>

And change the functions too:
private function close():void{
                        PopUpManager.removePopUp(this);
                        dispatchEvent(new Event("closepopup"));
                  }

And in eexchange.mxml...

                  private function init():void{
                        var pop:userentry = userentry(PopUpManager.createPopUp(this,userentry,true));
                        pop.addEventListener("closepopup",onClose);                        
                  }

Try those and let me know. If you could just send me your files I could correct those for you.



0
julianopolitoCommented:
another way could be the following:
You let the close event as it was close="removeMe()", and in the function you send a CloseEvent instead of an Event.

private function close():void{
           PopUpManager.removePopUp(this);
          dispatchEvent(new CloseEvent(CloseEvent.CLOSE));
}

anyway I still think it is strange, so again if you can send the code, I can understand it better and tell you

this might work too!
0
stockblocksAuthor Commented:
I'm glad you responded, because I gleefully report that my flex app is now working.  

As I stated previously, I inadvertently had the removeMe() called in the "close=" attribute of the TitleWindow tag.  After that was removed, the error went away.  But I still wasn't getting data populated in my main DataGrid.  So I ASSumed (note the caps there) that implied my close event wasn't being triggered. (sidenote: I guess some debug mode needs to pop up the trace() command, which I don't have enabled).

Your example code made absolute sense to me, so I did what I should have done when you first gave it to me: compile and run it!  Again, I didn't see the trace() kick in, so I just had a Label component on the main page fill in with text... anything to prove to myself that the event was triggered.  And sure enough, it was.

So it was obvious I was just screwing up elsewhere.  Without wanting to burden you with some side task, I credited your wonderful help with 500-points.  I solved my problem soon after.

If you're curious what it was, in the triggered close() event back in my main.mxml file, I was calling the RemoteService (that fills the DataGrid's ArrayCollection) without first setting a critical 'selectedIndex' value. Since it was initially set at -1, my query returned nothing, hence the empty DataGrid.  I forget to specify a selected index value of 0 in order to reflect the first entry in my ComboBox, and oooh-la-la...  it all fell into place quite beautifully.

I will no doubt have further questions in my Flex project.  Perhaps you'll be assisting me yet again in another EE Flex thread!

Thanks,

SB
0
julianopolitoCommented:
For sure, you can count on me for those here in experts-exchange. And even if you need my professional assistance and services we can talk either. I instruct flex/flash technology here in brazil, and I'm a certified expert and instructor at adobe. About screwing up the code forgeting the combo, take a look at my first post: mycombo.selectedIndex = 0;//selects first item
I think I was having some premonition on that... ;)) just in case you need to reach me my email is julianopolito at gmail.

Juliano Polito
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Apache Flex

From novice to tech pro — start learning today.