0
votes

I have the following situation:

I have an event handler, that displays small messages in my application's statusbar. These messages get passes through by dispatching events from custom components. A simple message could be like "HTTP Error" or so.

Now, the main event listener, in the main application file, listens to the event dispatched by any custom component, but seems to refuse listening to events dispatched by custom AS classes.

Here is my code for the custom event:

package main.events
{
    import flash.events.Event;

    public class ShowNoticeEvent extends Event
    {
        public var message:String;
        public static const SHOW_NOTICE:String = "showNotice";

        public function ShowNoticeEvent(type:String, msg:String, bubbles:Boolean = false, cancelable:Boolean = false)
        {
            super(type, bubbles, cancelable);
            this.message = msg;
        }

        override public function clone():Event
        {
            return new ShowNoticeEvent(type, message);
        }
    }
}

This is the event listener in the main application file:

addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);

And this is the custom AS class that dispatches the custom event. I pasted all the code, so you could see the whole part of it.

   package components.dashboard
{
    import components.dashboard.models.*;

    /* Event imports */
    import flash.events.*;
    import main.events.*;

    import mx.controls.Alert;
    import mx.core.UIComponent;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.http.HTTPService;

    [Event(name="showNotice", type="main.events.ShowNoticeEvent")]
    public class Controller extends UIComponent
    {
        private var baseUrl:String;

        public function Controller(baseUrl:String)
        {
            this.baseUrl = baseUrl;
        }

        public function getRunningQuotations():void
        {
            var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();

            execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations"); 
        }

        public function getRecentProjects():void
        {
            var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();

            execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
        }

        public function getLatestCustomers():void
        {
            var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();

            execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
        }

        private function execService(url:String, listener:Function, component:String):void
        {
            var basicService:HTTPService = new HTTPService(baseUrl);
            basicService.showBusyCursor = true;
            basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
            basicService.method = "POST";
            basicService.resultFormat = "text";
            basicService.url = url;
            basicService.addEventListener(ResultEvent.RESULT, listener);
            basicService.send();            
        }

        private function httpFault(event:FaultEvent, component:String = null):void {
            var faultstring:String = event.fault.faultString;
            var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true); 

            dispatchEvent(eventObj);
            trace(faultstring);
        }
    }
}

So to sum it all up: - The event listener listens to the custom event dispatched by any custom component. - The event listener does not listen to the custom event duspatched by an AS class.

Those who wonder, the event really gets dispatched, that's why I added a trace call.

2
Is your question "Why isn't my event handler executing code?" Or something else? Have you added the Controller class as a child to some container that is on the displayList? If not; the events won't bubble.JeffryHouser
Yes and no, the event handler only executes the code when the event is dispatched from within a child component, but not when it is dispatched from within an AS class. The controller class isn't a child of some container from the displayList, so it won't bubble. I don't think I can make it a child, or, I could in this case, but then I couldn't do that with my models, they aren't childs from anything I guess?Mortana
You should look at Robotlegs for a better way of handling communication among your Classes. A Controller Class should not be a View (which any Class extending UIComponent is), and so it should not be able to dispatch events against the display list itself. Not to mention that this is a Service Class, not a Controller Class at all. You might want to spend some time at AS3DP.com to get a feel for how to use design patterns to accomplish your goals, and not tightly couple your code by using Singletons tinyurl.com/4qq53yjAmy Blankenship
I only made this extend UIComponent, because I wasn't able to dispatch events, only when I extended that class. And yes, I know about the fact that this is actually more a model/service class, then a controller class, I'm working on putting all mxml AS code in a controller class, and putting the currentcontroller code in models. I don't see any singletons in my code atm? But I'll read your docs provided, thanks.Mortana
You can extend EventDispatcher to be able to dispatch events (or implement IEventDispatcher). In your code, RecentProjectsList.getInstance() stinks to high heaven like a Singleton. Just sayin'.Amy Blankenship

2 Answers

2
votes

The instance of Controller Class would have to be added to stage for that to work.

by doing

addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);

in the main file you are adding the listener to the stage.

So basically you are doing.

stage.addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true);

If controler instance is not on stage you won't see the event.

You might want to look into a Singleton type pattern for your data management as that would fit this setup pretty good.

0
votes

Main:

Controller.getLastInstance().addEventListener(ShowNoticeEvent.SHOW_NOTICE, showNoticeListener, true)

.

package components.dashboard
{
    import components.dashboard.models.*;

    /* Event imports */
    import flash.events.*;
    import main.events.*;

    import mx.controls.Alert;
    import mx.core.UIComponent;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.http.HTTPService;

    [Event(name="showNotice", type="main.events.ShowNoticeEvent")]
    public class Controller extends UIComponent
    {
        static public function getLastInstance():Controller { return _instance; }
        static private var _instance:Controller;
        private var baseUrl:String;

        public function Controller(baseUrl:String)
        {
            _instance = this;
            this.baseUrl = baseUrl;
        }

        public function getRunningQuotations():void
        {
            var runningQuotationsList:RunningQuotationsList = RunningQuotationsList.getInstance();

            execService("index.php?a=1", runningQuotationsList.updateList, "pnlRunningQuotations"); 
        }

        public function getRecentProjects():void
        {
            var recentProjectsList:RecentProjectsList = RecentProjectsList.getInstance();

            execService("index.php?a=2", recentProjectsList.updateList, "pnlRecentProjects");
        }

        public function getLatestCustomers():void
        {
            var latestCustomersList:LatestCustomersList = LatestCustomersList.getInstance();

            execService("index.php?a=3", latestCustomersList.updateList, "pnlLatestCustomers");
        }

        private function execService(url:String, listener:Function, component:String):void
        {
            var basicService:HTTPService = new HTTPService(baseUrl);
            basicService.showBusyCursor = true;
            basicService.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void{httpFault(e, component)});
            basicService.method = "POST";
            basicService.resultFormat = "text";
            basicService.url = url;
            basicService.addEventListener(ResultEvent.RESULT, listener);
            basicService.send();            
        }

        private function httpFault(event:FaultEvent, component:String = null):void {
            var faultstring:String = event.fault.faultString;
            var eventObj:ShowNoticeEvent = new ShowNoticeEvent(ShowNoticeEvent.SHOW_NOTICE, faultstring, true); 

            dispatchEvent(eventObj);
            trace(faultstring);
        }
    }
}

Not Ideal since you could only ever have 1 of them. But I think better than having to turn a simple EventDispatcher into DisplayObject and add it to stage just to Simply bubble.