7 Replies Latest reply on Jul 23, 2006 9:44 PM by jpwrunyan

    How do you cancel Events?

    jpwrunyan Level 1
      Here's what I am trying to do:
      I have a set of .mxml components comprising various "views" for my application. These views are a subclass of a template view.
      Each view has a "goBack" event which is dispatched via an outside Event managing utility (I have to do it this way because of the project's design specs... I can't just dispatch the event from within the component... ALL events, no matter how simple and straightforward have to go through the Event managing utility).

      Here's the structure:
      All these view components are inside a viewstack and their listener is set to a function on the application level:


      <mx:Application ..>
      __<mx:Script>
      ____private function goBack(e:Event):void {
      ______//a function that manages the ViewStack's selectedChild
      ____}
      __</mx:Script>
      __<mx:ViewStack>
      ____<CC:MainMenu />
      ____<CC:View1 goBack="goBack(event)" />
      ____<CC:View2 goBack="goBack(event)" />
      etc.

      now, the custom Event utility class does something like this:
      ..
      public static fuction handleEvent(ecode:String):void {
       //currentView being whatever the selectedChild of my Application's main ViewStack is
        if (ecode == "SOME_DOCUMENTED_CODE_NUMBER12345") {
         currentView.dispatchEvent(new Event("goBack"));
        }
      }

      but! on one particular view, I want to intercept the "goBack" event and instead of immediately calling the goBack listener on the application level, I want to open a confirmation dialog in the component. If the user confirms, then I want the application listener to fire and proceed as normal.

      The prolem is that no matter what I do, the event listener on the Application level always seems to fire before the listener on the component. I have tried setting bubbles, and cancelable in the constructor, tried making the event a MouseEvent, but to no avail. How can I set up my event so that it is detected by the component that originates the event and gets cancelled within the component.

      I realize there are other ways to do this, but I am forced to comply with strict specifications and must keep everything as compartmentalized as possible (thus no "confirm" event or if statements in the Applications goBack() method).

      If anyone can offer any adivce, I would greatly appreciate it.
        • 1. Re: How do you cancel Events?
          inlineblue Level 1
          When adding the component as its own listener, use addEventListener() and set its priority to be higher. eg:

          addEventListener("goBack", onGoBack, false, 10);

          The default priority is 0 (which I believe will be the priority of the application listener), so here I've set the view priority to be 10. This should get the view's listener to fire first. And if you need to cancel the event, call event.stopImmediatePropagation().
          • 2. Re: How do you cancel Events?
            jpwrunyan Level 1
            Thanks, that did the trick, also, I had to do one more thing:
            adding listeners in the MXML tag like this:
            <MC:View1 myEvent="someCode()" />
            adds the listener to fire during the capture phase so that it propogates from Application -> component.

            I had to set it specifically with "addListener" and set useCapture to false:

            <MC:View1 initialize="myApp.addListener('myEvent', handler, false)" />

            Done that way, stopImmediatePropogation() cancels the event before it bubbles up to the application.
            • 3. Re: How do you cancel Events?
              inlineblue Level 1
              Setting the handler in MXML adds the listener to the capture phase? Really? Is that in the docs? Can you point me there?
              • 4. Re: How do you cancel Events?
                jpwrunyan Level 1
                Ok, it doesn't say that explicitly in the docs, but here's what it does say:
                quote:


                Second, you register that function or class method with a display list object by using the addEventListener() method, as the following example shows:

                myButton.addEventListener(MouseEvent.CLICK, myEventListener);

                Most Flex controls simplify listener registration by letting you specify the listener inside the MXML tag. For example, instead of using the addEventListener() method to specify a listener function for the Button control's click event, you specify it in the click attribute of the <mx:Button> tag:

                <mx:Button id="b1" label="Click Me" click="myEventListener()"/>

                This is equivalent to the addEventListener() method in the previous code example. However, it is best practice to use the addEventListener() method. This method gives you greater control over the event by letting you configure the priority and capturing settings, and use event constants. In addition, if you use addEventListener() to add a listener, you can use removeEventListener() to remove the listener when you no longer need it. If you add an event listener inline, you cannot call removeEventListener() on that listener.


                This is in:
                Flex 2 Developer's Guide > Using Flex Programming Languages > Using Events > Using events

                if <mc:Comp myEvent="blah(event)"> is the same as: addEventListener("myEvent", blah), then it follows that setting the listener in the mxml tag sets up only for capturing.
                • 5. Re: How do you cancel Events?
                  inlineblue Level 1
                  No, addEventListener() defaults to only the bubbling phase. Look at the signature:

                  public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

                  • 6. Re: How do you cancel Events?
                    jpwrunyan Level 1
                    Huh, you're right. I guess I was confused about the defaults. Still, what doesn't make sense to me is that if it is set for bubbling, then why does the application listener fire before the listener I register in the component? Setting priority for listeners only matters when they are set at the same level (on the same object?). So does this mean that mxml tag listeners are actually on the component and not the application?
                    If so, then by setting the listener on the initialize event I am just putting it behind the order of the listener inside the component. But, then, before, I did try setting the priority of the listener in the component to be higher than that set in the mxml tag but it didn't work (the mxml tag listener still fired first). I'll have to go back and try again. I would definately rather use the MXML tag listener than set it with AS in the initialize event.
                    • 7. Re: How do you cancel Events?
                      jpwrunyan Level 1
                      Ah, I figured out how I got confused...
                      the default setting for new Event() is:
                      Event(type:String, bubbles:Boolean=false, cancelable:Boolean=false):Object