views:

33

answers:

3

I need to be able to call a method from a component located under the main application in Flex 4. Can anyone tell me please how to do this without using FlexGlobals please?

Sample code is attached. Thanks in advance.

// TestApp.mxml (application)
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                       xmlns:s="library://ns.adobe.com/flex/spark" 
                       xmlns:mx="library://ns.adobe.com/flex/mx"
                       creationComplete="initApp()">
    <fx:Script>
        <![CDATA[
            import com.TestComp;

            import mx.managers.PopUpManager;

            public function myMethod():void
            {
                // do something
            }

            protected function initApp():void
            {
                var popUp:TestComp = new TestComp();

                PopUpManager.addPopUp(popUp, this, true);
            }
        ]]>
    </fx:Script>
</s:WindowedApplication>

// TestComp.mxml (component)
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx"
         width="400" height="300">
    <fx:Script>
        <![CDATA[
            private function doSomething(event:MouseEvent):void
            {
                // call to myMethod() in TestApp.mxml
            }
        ]]>
    </fx:Script>
    <s:Button click="doSomething(event)" label="Click Me"/>
</s:Group>
+1  A: 

This is bad design. You should provide a callback function or an event listener.

// TestComp.mxml

<mx:Metadata>
  [Event(name="doSomethingEvent", type="flash.events.Event")]
</mx:Metadata>

<mx:Script><![CDATA[

  private function doSomething(event:MouseEvent):void
  {
    this.dispatchEvent(new Event("doSomethingEvent"));
  }

]]></mx:Script>

// TestApp.mxml
protected function initApp():void
{
  var popUp:TestComp = new TestComp();
  popUp.addEventListener("doSomethingEvent", myMethod);
  PopUpManager.addPopUp(popUp, this, true);
}

private function myMethod(event: Event): void
{
  // do something
}

And this is a callback example:

// TestComp.mxml

public var doSomethingCallback: Function;

private function doSomething(event:MouseEvent):void
{
  doSomethingCallback.call();
}

// TestApp.mxml
protected function initApp():void
{
  var popUp:TestComp = new TestComp();
  popUp.doSomethingCallback = myMethod;
  PopUpManager.addPopUp(popUp, this, true);
}

private function myMethod(): void
{
  // do something
}
splash
Nice! I'll opt for the Event method. Thanks very much.
Reado
A: 

I do agree with splash that it's bad design, but the following should work

//in TestApp
protected function initApp():void
{
  var popUp:TestComp = new TestComp(this);
  PopUpManager.addPopUp(popUp, this, true);
}

//in TestComp
private var app:TestApp;

public function TestComp(app:TestApp)
{
  this.app = app;
}

private function doSomething(event:MouseEvent):void
{
  // call to myMethod() in TestApp.mxml
  app.myMethod();
}

or you could do it this way

//in TestApp
protected function initApp():void
{
  var popUp:TestComp = new TestComp(this);
  popUp.addEventListener( 'test' , eventListener );
  PopUpManager.addPopUp(popUp, this, true);
}
private function eventListener(event:Event):void
{ 
   //in which case myMethod doesn't need to be public
   myMethod();
}

//in TestComp
private function doSomething(event:MouseEvent):void
{
  dispatchEvent( new Event('test') );
}
PatrickS
+1  A: 

Easiest option?

Take out the click handler from the button in TestComp.

In your main app, add a listener to TestComp (if it's a direct child of the main application) or itself (if TestComp is further down the display list) for MouseEvent.CLICK. In the handler, test to see if the event's target is the TestComp either through == if you've got a direct reference, or through "is" if not.

That's the least amount of effort from what you have just now, still relies on (bubbling) events, and is more "correct"

Gregor Kiddie