Event Propagation

Event Propagation

Each event in the flex framework is internally divided into "stages" which allows for a more controlled progression of processing for the event. The idea is that a particular handler may need to control, affect, or monitor the behavior of other handlers that may also be attached to the event. In such cases, it's necessary to ensure that your handlers are executed at certain "stages" of the event.

Advanced Usage: App.on('event-name', 'stage', Handler)

When you attach a handler to an event, you can specify a specific stage of the event you want your handler to execute in. This allows handlers to be prioritized (and even bypassed) during event propagation. When using the shorter App.on('event-name', Handler) method to attach a handler to an event (without specifying an explicit stage), flex will internally assign it to the 'process' stage by default.

Basic Event Stages

When an event is triggered by the flex framework, handlers for the event are executed in groups called "stages". By default, every event will follow a standard progression of event stages:

  • before : Do any preliminary setup stuff for the data processing.
  • process : Do regular data processing for the event during this stage.
  • render : Do manipulations and updates to the user interface during this stage.
  • after : Do any post-processing stuff for the event.

When an event is triggered, flex will begin to execute all handlers attached to the event; stage by stage. When executing handlers for a given event stage, they are executed in the order they were attached to that stage.

Custom Event Stages

Events can be made to progress through any number of customized stages in their life cycle. You may want to design your own events with custom stages to better serve the purpose of your event. For example, you may want your event to include an "init" stage that you can use to prepare the event object in your own way prior to the standard 'before', 'process', 'render', and 'after' stages. To create a custom event sequence, use the App.sequence() method.

Example:
flexloader.execute(function($, App) {
  App.sequence('custom-event-name', [ 'init', 'before', 'process', 'render', 'after' ]);
});

Customization of event stages are done "per event". The first parameter used in the method is the name of the event to re-sequence, and the second parameter is an array with the name of the different stages to implement (in the order that they should execute).

If you want to return the current sequence for a given event, call the App.sequence('event-name') method without the second "sequence" parameter. The return result will be an array of the current stages implemented for the event.

Regardless of the stages that you use and the order in which you use them, it is wise to implement a 'process' stage for your event so that handlers attached to your event using the shorter
App.on('custom-event-name', Handler) method will not be orphaned (since they are internally assigned to the 'process' stage by the framework).

Controlling Event Propagation

During event propagation, the event object has some internal methods available that can be used to control the flow of the event processing. With these methods, you can fork processing to handlers attached to another event, bypass certain stages of the current event, or even halt further processing of the event altogether.

Forking: event.fork(String : Array)

Whenever you use the event.fork() method in an event handler, you will give it either a single event name (string), or a list of event names (array). The fork events will be triggered immediately after the current stage of processing for the current event is complete, and before the next stage of processing for the current event begins. The event object will be shared with the forked events, and the arguments passed to the forked events will be the same arguments that were passed into the current event.

By forking an event, you are essentially adding a whole new series of stages into the current event flow since the forked event will also have its own full set of event stages that it will run through.

Bypassing: event.bypass(String : Array)

Whenever you use the event.bypass() method in an event handler, you will give it either the name of a single stage (string), or a list of stages (array). The stages given will then be bypassed in the current event as the progression moves forward.

Example:
flexloader.execute(function($, App) {

  /**
   *  Handle the "cart show" event and do our own
   *  thing if the cart is empty :p
   */

  App.on('bbflex-cart-show', 'before', function() {

    // access the event object
    var event = this;

    if (App.Cart.data().items.length == 0) {
      alert('Nothing in your shopping cart. Time to get shopping!');
      event.bypass('render');
    }

  });

});

Halting: event.halt()

You can use the event.halt() method in an event handler to stop any additional processing of the current event for the rest of this stage and any stages to follow. However, any events set with event.fork() will still be forked when the handler is finished, and if the event being halted was a fork of another event, the event that it was forked from will still continue its own propagation.

Example:
flexloader.execute(function($, App) {

  // access the event object
  var event = this;

  /**
   *  Halt the standard "playlists show" event and
   *  fork the event to your own handlers
   */

  App.on('bbflex-playlists-show', 'before', function() {
    event.halt();
    event.fork('mycustom-playlists-show');
  });

  /**
   *  Handle your custom "playlists show" event
   */

  App.on('mycustom-playlists-show', 'render', function() {
    // do your own stuff to show the playlists to the user
    alert('My own implementation of the show playlists feature...');
  });

});

Advanced Triggering

If you want to trigger only certain stages within an event, you can do that by specifying the stages to be executed (seperated by colons) after the event name when using the App.trigger() method. This format can also be used when specifying event names using the event.fork() method.

Example:
flexloader.execute(function($, App) {

  // trigger only the 'process' and 'render' stages of 'event-name'
  App.trigger('event-name:process:render', param);

});