22 Replies Latest reply on Mar 13, 2013 12:21 PM by sfisher_sticky_kiwi

    Custom Event Listener Callback fails

    sfisher_sticky_kiwi

      Good morning,

      I have a Flex 4.6 mobile project and I have created a custom event, I can see from various traces that the event is being dispatched as expected, but no matter what I do I cannot get a listener to work they just sit there and nothing ever happen, please take a look and tell me what could be wrong.

       

      Custom Event:

       

      package classes.events

      {

      import flash.events.Event;

      public class cartLoaded extends Event

      {

        public static const CART_LOAD_SUCCESS:String = "cartLoadSuccess";

       

        public function cartLoaded(type:String, bubbles:Boolean=false, cancelable:Boolean=false)

        {

         trace("event_dispatched");

         super(type, bubbles, cancelable);

        }

       

        override public function clone():Event

        {

         trace("event_cloned");

         return new cartLoaded(type, bubbles, cancelable);

        }

      }

      }

       

      The event is dispatched from a class, after a ResultEvent from a webservice call, so in the ResultEvent callback I have:

       

      var cl:cartLoaded = new cartLoaded(cartLoaded.CART_LOAD_SUCCESS);

      e.currentTarget.dispatchEvent(cl);

       

      And I see 'event_dispatched' in the console when my results come back. So I know that the event is fired. Now on the Main Application file, in the ViewInit, on a list, on a view I add, I have basically tried this everywhere.

       

      lst_cart.addEventListener(cartLoaded.CART_LOAD_SUCCESS,loadData);

      function loadData(e:cartLoaded):void

      {

      trace("set data provider");

      }

       

       

      I never see 'set data provider', now I understand that the listener must be registered before the event is dispatched, and in my case it certainly is:

       

      I have a view (have tried doing addEventListener here in an initialize handler)

      the view contains a list with a custom item renderer (have tried it here(

      the itemrenderer contains a button (have tried it here)

      the button calls a method in a class that triggers a web service call (this is where the dispatch event is done)

      the web service call fires a result event

      the result event fires my custom event

       

      Please help, as this is seriously preventing me from moving forward, I need to be able to capture this event, and I have tried everything.

       

      Regards

      Shaine

       

      Message was edited by: sfisher_sticky_kiwi

        • 1. Re: Custom Event Listener Callback fails
          sfisher_sticky_kiwi Level 1

          Funnily enough, this is the ONLY way I can make it work:

           

          //add listener

          testbtn.addEventListener(MouseEvent.CLICK,me);

          testbtn.addEventListener(cartLoaded.CART_LOAD_SUCCESS,you);

            

          function you(e:cartLoaded):void

          {

          //listen for event

          trace("listener fired");

          }

          function me(e:MouseEvent):void

          {

          //dispatch event

          var cl:cartLoaded = new cartLoaded(cartLoaded.CART_LOAD_SUCCESS);

          e.currentTarget.dispatchEvent(cl);

          }

           

          So I know it is possible, but this fails:

           

          protected function view1_initializeHandler(event:FlexEvent):void

             {

              //add listener

              testbtn.addEventListener(MouseEvent.CLICK,me);

              this.addEventListener(cartLoaded.CART_LOAD_SUCCESS,you);

             

              function you(e:cartLoaded):void

              {

               //listen for event

               trace("listener fired");

              }

              function me(e:MouseEvent):void

              {

               //dispatch event

               var cl:cartLoaded = new cartLoaded(cartLoaded.CART_LOAD_SUCCESS);

               e.currentTarget.dispatchEvent(cl);

              }

             }

           

          So still looking for an answer, please.

           

          Regards

          Shaine

          • 2. Re: Custom Event Listener Callback fails
            LucasAlex Level 1

            Try setting bubbles to true.

            public function cartLoaded(type:String, bubbles:Boolean=true, cancelable:Boolean=false)

            • 3. Re: Custom Event Listener Callback fails
              pauland Level 4

              ..and name your classes starting with a capital letter..

              • 4. Re: Custom Event Listener Callback fails
                sfisher_sticky_kiwi Level 1

                I had already tried this, and various combinations depending on the code sample I found, thank you, but sadly not a solution.

                 

                Shaine

                • 5. Re: Custom Event Listener Callback fails
                  sfisher_sticky_kiwi Level 1

                  That is a convention I cannot get into, I always have up to now started with a lower case letter, and prefixed vars the other way, I will change how I do it, but that is only convention, in this case it would not cause the issue. But as you brought it up, why? why is it convention to start class names with a capital letter? Just interested really.

                   

                  Shaine

                  • 6. Re: Custom Event Listener Callback fails
                    pauland Level 4

                    Shaine, the principle of event propogation is very simple.

                     

                    If you don't bubble your event dispatches, the only listener capable of picking up the event has to be attached to the dispatcher.

                     

                    If your event bubbles, any listener attached to the display tree higher up than the dispatcher, will receive the event.

                     

                    If you are bubbling events and not receiving them, then you aren't adding the event listener in the right place,

                    • 7. Re: Custom Event Listener Callback fails
                      pauland Level 4

                      why is it convention to start class names with a capital letter?

                       

                      The reason is that whenever you look at some code and see an identifier that starts with a capital letter and uses camel-case, you know it's a class not a variable or function call.

                       

                      If you see something named with a lower-case letter at the start, you know instantly that it's a variable or function of some kind.

                       

                      The convention makes code much easier to read. This is the established convention and you absolutely should stick with it.

                      • 8. Re: Custom Event Listener Callback fails
                        sfisher_sticky_kiwi Level 1

                        If you don't bubble your event dispatches though dont you have the option of adding [Event(name="cartLoaded", type="classes.events.cartLoaded")] to the element that dispatches the event? Which I did.

                         

                        Here is what I would like to happen, the web service call raises a result event, and then my event is dispatched, and then either the initial button that launched the cart web service call, or the list lst_cart to receive the notification.

                         

                        Sadly, despite adding the above code to the class file (inside the package statement but outside the class so it afects all methods) and turning bubbling=true, I cannot seem to get this to work.

                         

                        Let me experiment for a bit, I will come back and update you soon, thank you very much for your help so far, and I know I can get this working

                        • 9. Re: Custom Event Listener Callback fails
                          pauland Level 4

                          While you can add an event listener to the button itself, it's pretty much certain it's the wrong place to have the listener, logically.

                           

                          Revisit some of the online tutorials on event propagation and perhaps look at the MVC pattern.

                          • 10. Re: Custom Event Listener Callback fails
                            sfisher_sticky_kiwi Level 1

                            The original post may not have been as clear as it could have beem. So I will try to explain simply what is happening.

                             

                            I have a list, called lst_cart, which has an itemrenderer inside, this item renderer contains a button that when clicked makes a method call to a class which makes a web service call, the web service call has an event listener on the result event. The result event dispatches my custom event (cartLoaded), this dispatch is occuring because I have a trace that tells me so.

                             

                            On the parent list (lst_cart) I have an event listener that listens for the custom event being triggered. This event is never received.

                             

                            I have edited the event to make bubbles = true, although I was under the impression that having [Event(name="cartLoaded", type="classes.events.cartLoaded")] negated the need for this. This line is outside the class itself but inside the package.

                             

                            I tied the event dispatcher and listener to a button to test if it ever worked, and it does, but only if they are tied to the same component, I have now removed this

                             

                            Now all naming conventions aside, this isnt my original code, I have inherited this part from a previous dev, is there anything wrong with the code that would stop me from being able to receive the event on the list that the listener is tied to?

                             

                            I also tried to tie the listener to the parent view of the list, and this failed, I have been reading and testing a lot of things before I posted here and I am not having much success, I was hoping for some help with the actual code problem I am having, I hope this clears up the situation and allows you to see what I am trying to do, and gets us to an answer.

                             

                            Thanks
                            Shaine

                            • 11. Re: Custom Event Listener Callback fails
                              pauland Level 4

                              the button calls a method in a class that triggers a web service call

                               

                              Classes don't fire events - instances do - and that instance must itself be attached to the display list, otherwise the event cannot bubble up the display tree.

                               

                              Every instance involved in the dispatch must be attached to the display tree.

                              1 person found this helpful
                              • 12. Re: Custom Event Listener Callback fails
                                sfisher_sticky_kiwi Level 1

                                I marked your answer as helpful because it was, I want to change it to correct, but we are missing a valuable bit of information, how?

                                 

                                How do I make this event do what I want, or is it not actually possible?

                                 

                                Please, just this once cut me some slack, this has been a nightmare, I would hazzard a guess that I do create an instance of the class with:

                                 

                                mycart:cart = new cart();

                                cart.additem();

                                 

                                But as a secondary thought, the class extends nothing, so do I need to extend UIComponent?

                                 

                                My back is against the wall with this, I just want to get it done and then build the thing again from scratch my way, my boss has spent (see wasted) a lot of money on this project, so please, just one last hint to complete.

                                 

                                Shaine

                                • 13. Re: Custom Event Listener Callback fails
                                  pauland Level 4

                                  Shaine, we're only seeing a bit of the picture and while I don't mind giving a nudge along the way, I'm not here to be a backstop debugging other people's code.

                                   

                                  I sympathise with your position, but you're clearly not yet experienced enough with the propogation model to properly understand the issues.

                                   

                                  Here is a crude example of a VERY BAD practice of dispatching and receiving events using the stage. You may be able to use this trick.

                                   

                                  When the button is clicked it moves down 10 pixels, when the event is handled it moves the button across 100 pixels.

                                   

                                  This is very bad practice and shouldn't be used normally.

                                   

                                  Paul

                                   

                                  <?xml version="1.0" encoding="utf-8"?>

                                  <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

                                                 xmlns:s="library://ns.adobe.com/flex/spark"

                                                 xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" applicationComplete="onAppComplete(event)">

                                      <fx:Declarations>

                                          <!-- Place non-visual elements (e.g., services, value objects) here -->

                                      </fx:Declarations>

                                      <fx:Script>

                                          <![CDATA[

                                             

                                              private function onAppComplete(e:Event):void {

                                                  stage.addEventListener("SOME_EVENT", onSomeEvent );

                                                  btn.x=10;

                                              }

                                             

                                              private function onSomeEvent(e:Event):void{

                                                  trace("got "+e.type);

                                                  btn.x += 100;

                                                 

                                              }

                                             

                                              private function onClick(e:Event):void{

                                                  trace("sending SOME_EVENT ");

                                                  dispatchEvent(new flash.events.Event("SOME_EVENT", true));

                                                  btn.y += 10;

                                              }

                                          ]]>

                                      </fx:Script>

                                      <s:Button id="btn" label="click me" click="onClick(event)" />

                                   

                                  </s:Application>

                                  1 person found this helpful
                                  • 14. Re: Custom Event Listener Callback fails
                                    sfisher_sticky_kiwi Level 1

                                    I do understand that, and I do appreciate what you are saying, so, one last post to see if this will ever make sense, this is a cut down version of the actual code in use:

                                     

                                    cartLoaded.as

                                     

                                    package classes.events

                                    {

                                              import flash.events.Event;

                                              public class cartLoaded extends Event

                                              {

                                                        public static const CART_LOAD_S:String = "cartLoadS";

                                     

                                                        public function cartLoaded(type:String, bubbles:Boolean=true, cancelable:Boolean=false)

                                                        {

                                                                  trace("eventcalled");

                                                                  super(type, bubbles, cancelable);

                                                        }

                                     

                                                        override public function clone():Event

                                                        {

                                                                  return new cartLoaded(type, bubbles, cancelable);

                                                        }

                                              }

                                    }

                                     

                                     

                                    the cart class, called Cart.as

                                     

                                    package classes.data.cart

                                    {

                                              //imports removed

                                     

                                    [Event(name="cartLoaded", type="classes.events.cartLoaded")]

                                              public class Cart

                                              {

                                                        public function Cart()

                                                        {

                                                        }

                                                        public function Create():ArrayCollection

                                                        {

                                                                  //fluff code removed

                                                                  CartCreateResult.token = commerceCart._skc_CartCreate(obj.item, obj.ResponderType);

                                                                  CartCreateResult.addEventListener(ResultEvent.RESULT,lstnr_CartCreateResul t);

                                                                  function lstnr_CartCreateResult(e:ResultEvent):void

                                                                  {

                                                                            //fluf removed

                                                                            results.list = CartCreateResult.lastResult.Cart[0].CartItems.CartItem;

                                     

                                                                            //dispatch event

                                                                            var cl:cartLoaded = new cartLoaded(cartLoaded.CART_LOAD_S);

                                                                            e.currentTarget.dispatchEvent(cl);

                                                                  }

                                                        }

                                              }

                                    }

                                     

                                     

                                    Item renderer that calls the above class:

                                     

                                    <s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"

                                                                            xmlns:s="library://ns.adobe.com/flex/spark"

                                                                            xmlns:fxg="assets.fxg.*"

                                                                            height="180" autoDrawBackground="false"

                                                                            cacheAsBitmap="true" initialize="initializeHandler(event)"

                                                                            opaqueBackground="0xFFFFFF">

                                     

                                              <fx:Script>

                                                        <![CDATA[

                                                                  override public function set data(value:Object):void

                                                                  {

                                                                            super.data = value;

                                     

                                                                            if (data)

                                                                            {

                                                                                      //removed

                                                                            }

                                                                            else

                                                                            {

                                                                                      //removed

                                                                            }

                                                                  }

                                     

                                                                  override protected function measure():void

                                                                  {

                                                                            //removed

                                                                  }

                                                                  protected function lstnr_cartAdd(e:MouseEvent):void

                                                                  {

                                                                            if(so.data.cartIdentityObj){

                                                                                      cart = new Cart();

                                                                                      cart.Add();

                                                                            }else{

                                                                                      cart = new Cart();

                                                                                      cart.Create();

                                                                            }

                                                                  }

                                                                  private function lstnr_cartAdded(e:cartLoaded):void

                                                                  {

                                                                            trace("event received")

                                                                            btn_AddToCart.label = "Add to Basket";

                                                                            //btn_AddToCart.enabled = true;

                                                                  }

                                                        ]]>

                                              </fx:Script>

                                              <s:Button label="Add" click="lstnr_cartAdd(event)"/>

                                    </s:ItemRenderer>

                                     

                                     

                                    The view tat uses the renderer:

                                     

                                    <?xml version="1.0" encoding="utf-8"?>

                                    <s:View xmlns:fx="http://ns.adobe.com/mxml/2009"

                                                        xmlns:s="library://ns.adobe.com/flex/spark"

                                                        creationComplete="view_creationCompleteHandler(event)"

                                                        initialize="view_initializeHandler(event)">

                                              <fx:Metadata>

                                                        [ResourceBundle("LocalizedStrings")]

                                              </fx:Metadata>

                                              <s:layout>

                                                        <s:VerticalLayout gap="3" paddingBottom="5" paddingLeft="10" paddingRight="10" paddingTop="5"/>

                                              </s:layout>

                                              <fx:Script>

                                                        <![CDATA[

                                                                  // startup function

                                                                  private function view_initializeHandler(event:FlexEvent):void

                                                                  {

                                                                            this.lst_ProductAvailability.addEventListener(cartLoaded.CART_LOAD_S, lstnr_cartAdded);

                                                                            this.addEventListener(cartLoaded.CART_LOAD_S,lstnr_cartAdded2)

                                                                  }

                                     

                                                                  private function lstnr_cartAdded(e:cartLoaded):void

                                                                  {

                                                                            trace("detail view event received")

                                                                  }

                                                                  private function lstnr_cartAdded2(e:cartLoaded):void

                                                                  {

                                                                            trace("detail view event received 2")

                                                                  }

                                     

                                                        ]]>

                                              </fx:Script>

                                     

                                                                  <!-- AVAILABILITY -->

                                                                  <s:VGroup id="isAvailable" width="100%">

                                                                            <s:List id="lst_ProductAvailability" width="100%"

                                                                                                itemRenderer="renderers.mxml.rendererAddToCart"

                                                                                                scrollSnappingMode="leadingEdge" verticalScrollPolicy="off">

                                                                                      <s:layout>

                                                                                                <s:HorizontalLayout gap="0"/>

                                                                                      </s:layout>

                                                                            </s:List>

                                                                  </s:VGroup>

                                    </s:View>

                                     

                                     

                                    This is the actual code, hopefully it makes sense. I dont want you to be my back end code debugger, I am perfectly capable of doing that myself, but I have obviously missed something and I just dont know where to look any more.

                                     

                                    Thanks for your patience.

                                    Shaine

                                    • 15. Re: Custom Event Listener Callback fails
                                      LucasAlex Level 1

                                      Your Cart object dispatches this cartLoaded event, but since the object is not in the display list, nobody can catch the event, there's no parent to bubble to.

                                      I wonder how does it manage to catch the ResultEvent.

                                      • 16. Re: Custom Event Listener Callback fails
                                        pauland Level 4

                                        Yes, this has to be one of the most convoluted things I've come across.

                                         

                                        cart.Create(); issues the event, but isn't attached to the display list.

                                         

                                        CartCreateResult is dispatching a new event when the cart contents are loaded and I guess that e.currentTarget is perhaps CartCreateResult and is not on the display list either.

                                         

                                        The "superfluous code" may have been removed, but CartCreateResult is important and it's not defined anywhere we can see.

                                        • 17. Re: Custom Event Listener Callback fails
                                          LucasAlex Level 1

                                          He removed some code, probably was in there somewhere, otherwise it wouldn't compile.

                                          • 18. Re: Custom Event Listener Callback fails
                                            pauland Level 4

                                            Yes, of course, but it's vital to know how it's declared and used because it needs to be on the display list.

                                             

                                            It's a bit unfair of your boss to ask you to take this on Shaine.

                                            • 19. Re: Custom Event Listener Callback fails
                                              sfisher_sticky_kiwi Level 1

                                              package classes.data.cart

                                              {

                                                        import classes.customObjects.cartAddItem;

                                                        import classes.customObjects.cartClearItem;

                                                        import classes.customObjects.cartCreateItem;

                                                        import classes.customObjects.cartGetItem;

                                                        import classes.events.cartLoaded;

                                               

                                                        import mx.collections.ArrayCollection;

                                                        import mx.core.FlexGlobals;

                                                        import mx.core.UIComponent;

                                                        import mx.rpc.CallResponder;

                                                        import mx.rpc.events.FaultEvent;

                                                        import mx.rpc.events.ResultEvent;

                                               

                                                        import services.commercecart.CommerceCart;

                                               

                                                        public class Cart

                                                        {

                                                                  private var cartgs:CartGS;

                                               

                                                                  public function Cart()

                                                                  {

                                                                  }

                                                                  public function Create():ArrayCollection

                                                                  {

                                                                            var results:ArrayCollection = new ArrayCollection();

                                                                            var a:CartGS = new CartGS();

                                                                            var obj:cartCreateItem = a.CartCreateObject;

                                                                            var CartCreateResult:CallResponder = new CallResponder();

                                                                            var commerceCart:CommerceCart = new CommerceCart();

                                                                            CartCreateResult.token = commerceCart._skc_CartCreate(obj.item, obj.ResponseGroup);

                                                                            CartCreateResult.addEventListener(ResultEvent.RESULT,lstnr_CartCreateResul t);

                                                                            CartCreateResult.addEventListener(FaultEvent.FAULT,lstnr_CartCreateFault);

                                                                            function lstnr_CartCreateResult(e:ResultEvent):void

                                                                            {

                                                                                      var cartIdentity:cartGetItem = new cartGetItem();

                                                                                      cartIdentity.CartId = CartCreateResult.lastResult.Cart[0].CartId;

                                                                                      cartIdentity.HMAC = CartCreateResult.lastResult.Cart[0].HMAC;

                                                                                      cartIdentity.PurchaseURL = CartCreateResult.lastResult.Cart[0].PurchaseURL;

                                                                                      cartIdentity.ResponseGroup = new ArrayCollection(new Array("Cart"));

                                                                                      cartgs = new CartGS();

                                                                                      cartgs.CartIdentity = cartIdentity;

                                                                                      //other item objects

                                                                                      //***************************

                                                                                      //result

                                                                                      results.list = CartCreateResult.lastResult.Cart[0].CartItems.CartItem;

                                               

                                                                                      //dispatch event

                                                                                      var cl:cartLoaded = new cartLoaded(cartLoaded.CART_LOAD_S);

                                                                                      e.currentTarget.dispatchEvent(cl);

                                                                                      //***************************

                                                                            }

                                                                            function lstnr_CartCreateFault(e:FaultEvent):void

                                                                            {

                                                                                      trace("error in:CartCreate");

                                                                                      FlexGlobals.topLevelApplication.tracker.trackPageview("/error?method= CartCreate");

                                                                            }

                                                                            return results;

                                                                  }

                                                        }

                                              }

                                               

                                              hope this helps. shaine

                                              • 20. Re: Custom Event Listener Callback fails
                                                pauland Level 4

                                                Shaine, it shows that CartCreateResult is not attached to the Display list (nor should it really be, given what it's used for), so the ensuing event despatch won't bubble.

                                                 

                                                This programming by proxy isn't really working. I think that whatever advice you're given, the concepts are a bit beyond you right now and we'll just get back "it doesn't work".

                                                1 person found this helpful
                                                • 21. Re: Custom Event Listener Callback fails
                                                  Sean@Tier1CRM

                                                  pauland is right that there is a loss in the event chain, as the wrapper can't listen for it on the List because the list itself is not part of the event hierachy.

                                                   

                                                  I would think you can get around this in a couple of ways.

                                                   

                                                  1. Have your Cart class extend the EventDispatcher class. If this isn't possible at the very least implement an IEventDispatcher interface, and have a composite object which is the event dispatcher. Either way having the cart class be a form of an event dispatcher.
                                                  2. Have your item renderer listen for the event on the Cart class directly.
                                                  3. From your item renderers event handler, dispatch another event that bubbles up the display object hiearchy.

                                                   

                                                  Something like this:

                                                   

                                                  public class Cart extends EventDispatcher
                                                  {     
                                                       public function doStuff() : void
                                                       {
                                                            ...
                                                            dispatchEvent(...);
                                                       }
                                                  }
                                                  
                                                  OR if you can't extend it
                                                  
                                                  public class Cart implements IEventDispatcher
                                                  {
                                                       private var _eventDispatcher:EventDispatcher;
                                                       //contains all the methods of the IEventDispatcher interface but uses a facade layer
                                                       public function Cart()
                                                       {
                                                            _eventDispatcher = new EventDispatcher();
                                                       }
                                                  
                                                       public function addEventListener(params...) : void
                                                       {
                                                            _eventDispatcher.addEventListener(params...);
                                                       }
                                                  
                                                       public function doStuff() : void
                                                       {
                                                            ...
                                                            _eventDispatcher.dispatchEvent(...);
                                                       }
                                                  }
                                                  
                                                  public class MyItemRenderer
                                                  {
                                                       public function buttonClick() : void
                                                       {
                                                            var cart:Cart = new Cart();
                                                            cart.addEventListenerer(...);
                                                            cart.doStuff();
                                                       }
                                                  
                                                       public function doStuffEventListener(event:Event) : void
                                                       {
                                                            //Make sure the bubbles property is set to true
                                                            dispatchEvent(event.clone());
                                                       }
                                                  }
                                                  

                                                   

                                                  This should ensure that the event now is on the display list queue... though it's probably not a good idea to constantly be adding event listeners for this, it's probably better just to have a callback function and pass it to the item renderers to pass into the cart's process function.

                                                  • 22. Re: Custom Event Listener Callback fails
                                                    sfisher_sticky_kiwi Level 1

                                                    Despite the fact that this code is god awful, the only thing I had nor realised is that the bubbles had to up through the display list, well I did, but I had not made the connection that my class had not got that capability/ I apologise to you all.

                                                     

                                                    I do, believe it or not, know what I am doing most of the time,but on this occaision this single bit of code has killed me off, so thank you for your help.

                                                     

                                                    And although as expected, I am unable to im[plement the code suggested (extending didn't work) I have decided that code is so broken I am going to rewrite the whole damned thing, maybe writing this cart code as a real cusom component.

                                                     

                                                    Again, thanks one and all for you time, patience and assistance.

                                                     

                                                    Shaine