0

Hi guys i am trying to call a function which is defined in main.mxml

   public function btnAcceptCall_clickHandler(event:MouseEvent)
    {
     .....
     }

now i have a component mxml which calls this function

in this mxml i have defined a function

private function addNewCaller(event:MouseEvent):void
        {
           mx.managers.PopUpManager.removePopUp(this);
           Main.btnCallAndProfile_clickHandler(event)
        }

The problem is it gives an error

Call to a possibly undefined method btnCallAndProfile_clickHandler through a reference with static type Class.

anyone can point out what is the problem.??

Regards

Muhammad Umar
  • 11,391
  • 21
  • 91
  • 193

3 Answers3

5

You're coding it wrong. First off, Main.btnCallAndProfile_clickHandler is not static as mentioned in the error, nor would you want it to be static. You'll want to get an instance of Main for it to work, but for you to do that would mean that you would break good practice.

Flex is an event based language, and hence to separate concerns, you can use events to do the work for you. In this case, in Main, you would add an event listener (like say in the creationComplete event handler):

private function onCreationComplete():void
{
   addEventListener('callAndProfile', btnCallAndProfile_clickHandler);
}

And then from your addNewCaller function, you would do:

private function addNewCaller(event:MouseEvent):void
{
  dispatchEvent(new Event('callAndProfile', true));
}
J_A_X
  • 12,857
  • 1
  • 25
  • 31
5

J_A_X answer is pretty good, but there's another way that can still be considered clean code.

Define an interface:

interface AcceptCallHandler
{
    function acceptCall(e:MouseEvent):void;
}

Then you can implement this interface in your main.mxml and inject an AcceptCallHandler-instance into your component:

<s:Application implements="com.package.handlers.AcceptCallHandler" ...>
    <fx:Script>
        <![CDATA[
            public function acceptCall(e:MouseEvent):void
            {
                //...
            }
        ]]>
    </fx:Script>

    <component:SomeComponent acceptCallHandlerImpl="{this}"/>
</s:Application>

All you need to do in SomeComponent is:

class SomeComponent
{
    private var _acceptCallHandler:AcceptCallHandler;
    public function set acceptCallHandlerImpl(value:AcceptCallHandler):void
    {
        _acceptCallHandler = value;
    }

    private function addNewCaller(event:MouseEvent):void
    {
        mx.managers.PopUpManager.removePopUp(this);
        _acceptCallHandler.acceptCall(event);
    }
}

Using the events mechanism (and the Observer-design pattern) is not the only tool to promote loose coupling. In the above sample I'm demonstrating another 2 powerful techniques - programming to interfaces and dependency injection.

Vladimir Tsvetkov
  • 2,983
  • 3
  • 26
  • 36
  • Using Events IS the observer pattern. It's still not really good technique to give a reference to the parent into the child, especially since, with Events, you don't need to. – Amy Blankenship Oct 12 '11 at 11:54
  • To be precise the Events-mechanism implementation in Flash is actually a combination of 2 patterns - **Observer**, but also **Chain of Responsibility**. Adding an event listener is another way of creating a reference. In the case of a parent listening to child events, the direction of the reference is from the child to the parent, which is virtually the same thing (but more implicit and abstracted by the EventDispatcher-implementation). – Vladimir Tsvetkov Oct 12 '11 at 12:08
  • In my sample it is abstracted by the interface. **Both practices are trivially the same in regards with references.** Using Events is a better technique simply because the Observer pattern allows you to have multiple interested parties, while in my sample I'm limiting that only to the injected AcceptCallHandler implementor. – Vladimir Tsvetkov Oct 12 '11 at 12:09
  • 1
    It's only Chain of Responsibility (sort of) when you are using it for things like keyboard handlers, where every handler has to first determine if the event in question is for the actual key it cares about. If you noticed in the example posted by J_A_X, the event was a *bubbling* event, and hence the child did not need to get a reference to the parent (the event listener could be added by the main application to itself--which is what his code did). – Amy Blankenship Oct 12 '11 at 16:35
  • 1
    True! That was a very important detail that somehow I've missed! Thanks, Amy! – Vladimir Tsvetkov Oct 12 '11 at 17:06
  • Just to add that the event does not have to be **bubbling**. The event listener could be added by the main application to itself with the `useCapture`-argument set to true. But keep in mind that capturing event listeners can be added only in AS3-code. It won't work in MXML. – Vladimir Tsvetkov Oct 12 '11 at 20:00
0

If main.mxml is you default application. You can do this:

Application.application.btnCallAndProfile_clickHandler(event);

Matt MacLean
  • 19,410
  • 7
  • 50
  • 53