Home  >  

Disabling events in Flex

Author photo
December 16, 2009 | | Comments (5)
AddThis Social Bookmark Button

Flex does not provide a way to temporarily disable event listeners and re-enable them later.  You may want to do this to prevent endless loops.  For example, when some code modifies the selectedIndex of a List, an event is fired.  If you have a listener that reacts to the event, you may need a way of suppressing the listener's response under certain conditions.  You have two choices:

  • Couple the listener to the code that generates the event, so it knows when to ignore the event.  This defeats one of the purposes of event-driven programming, separation of concerns.
  • Suppress the event dispatch
My gift to you today, dear reader, is the EventManager class.  This class remembers all event listeners assigned to an EventDispatcher, and can remove or re-instate those listeners with a single method call.

package events {
    import flash.events.EventDispatcher;
    
    public class EventManager {
        private var dispatcher:EventDispatcher;
        private var type:String;
        private var listener:Function;
        private var useCapture:Boolean;
        private var priority:int;
        private var useWeakReference:Boolean;
        
        public function EventManager(dispatcher:EventDispatcher, type:String, listener:Function, useCapture:Boolean, priority:int, useWeakReference:Boolean) {
            this.dispatcher = dispatcher;
            this.type = type;
            this.listener = listener;
            this.useCapture = useCapture;
            this.priority = priority;
            this.useWeakReference = useWeakReference;
        }
        
        private static function disableFn(item:*, index:int, array:Array):void {
            var em:EventManager = EventManager(item);
            em.dispatcher.removeEventListener(em.type, em.listener, em.useCapture);
        }
        
        public static function disableAll(listeners:Array):void {
            listeners.forEach(disableFn);
        }
        
        private static function enableFn(item:*, index:int, array:Array):void {
            var em:EventManager = EventManager(item);
            em.dispatcher.addEventListener(em.type, em.listener, em.useCapture, em.priority, em.useWeakReference);
        }
        
        public static function enableAll(listeners:Array):void {
            listeners.forEach(enableFn);
        }
    }
}
Here is how you could use EventManager:

package {
public class EMDemo extends ComboBox {
private var listeners:Array = new Array();

override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
super.addEventListener(type, listener, useCapture, priority, useWeakReference);
listeners.push(new EventManager(this, type, listener, useCapture, priority, useWeakReference));
}

/** Prevent update events from being issued */
public function quietlySetIndex(newIndex:int):void {
EventManager.disableAll(listeners);
selectedIndex = newIndex;
EventManager.enableAll(listeners);
}
}
}

Read more from Mike Slinn. Mike Slinn's Atom feed mslinn on Twitter

Comments

5 Comments

Amy said:

That's very cool. You could probably use a similar technique to let you use event pooling to improve performance.

For other readers who may not have run across the concept of event pooling, it turns out that you don't have to create a new event each time you want to dispatch one...instead you can redispatch one you created earlier. This means that you can keep a pool of events and remove the overhead of instantiating the event objects.

huiles de poisson said:

Hi,
jQuery makes event pooling simple through the use of jQuery.bind() and jQuery.trigger().
This is the good step towards building an advanced Javascript Application since we can now bind methods to unique location.hash’s.
huiles de poisson

Glen said:

Isn't there a third choice ... delaying setting the property until you are truly ready for the property to be set?

(using the Flex Life Cycle methods, instead of creating your own life cycle)

It would seem that you could do your on-going logic by modifying a local var. Then, when you are finished with your logic, you could call invalidateProperties().

Your commitProperties() method could do the actual setting of the selectedIndex property.

Frank said:

Hi,
As huiles de poisson says it is possible to do this in a robust manner using jQuery, On my holidays to greece I met a guy who showed me how to do this, as i'm not the best using jQuery.

Kate said:

Nice post, keep up the good work. You could probably use a similar technique to let you use event pooling to improve performance. If you are in the market for computertodays, here's the guide that you've been looking for.

Leave a comment


Type the characters you see in the picture above.


Tag Cloud

iPad

What's your take on the iPad? (Putting aside the Flash/iPad flame war)

Answer

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.