---
title: Infusion Event System
category: Infusion
---
Infusion **events** are one of the most basic and widely used facilities in the framework. Almost every Infusion
component exposes one or more events and/or listeners to events fired by itself or other components. A component opts in
to the event system by mentioning `fluid.component` or some other grade derived from it such as `fluid.viewComponent` in
its list of parent [Component Grades](ComponentGrades.md).
An Infusion event (or more precisely, a particular firing of an Infusion event) represents
1. a particular instant in time (corresponding to when it is fired)
2. a particular array of JavaScript objects, forming its arguments or signature (sometimes called its *payload*).
An Infusion event can be fired at any time, and any collection of JavaScript objects can be supplied as its payload -
that is, any JavaScript function call can serve as the initiation point where an event is fired.
Rather than firing and listening to events in raw JavaScript code, we recommend using the framework to encode firing and
listening to events declaratively. We'll show how this syntax works first, and then later show procedural equivalents
and more details.
## Declaring an event on a component
A top-level options block named **`events`** is supported on every component derived from the core framework grade
`fluid.component`. The keys in this block represent the event name, and the values represent the type of the event.
Currently only two event types are supported, represented by the values `null` and `preventable` (this second value is
almost never used). This table explains the meaning of the two values:
Type |
Description |
null |
The standard right hand side in an events structure - this indicates a standard event which may have
any number of listeners and with no other special semantic
|
preventable |
The event represents a preventable action.
The listeners may each return a boolean value of false , representing both
- that further listeners should fail to be queried, and
- that the operation represented by the event should be cancelled.
This is similar to the default semantics on browser events.
|
Note: `preventable` events are very rarely used and will soon be deprecated in the framework.
For every such entry in the `events` section of a component's options, the framework will construct a corresponding
**event firer** with the same name in the `events` section of the constructed component. The most common use of an event
firer is to call its member named `fire` with some set of arguments. Here is a simple, self-contained example:
```javascript
fluid.defaults("examples.eventedComponent", {
gradeNames: ["fluid.component"],
events: {
myEvent: null
}
});
var myComponent = examples.eventedComponent();
myComponent.myEvent.fire(97, false);
// firer of event can supply whatever arguments they like,
// but these should conform to some agreed signature
```
As a real-world example, here is a block of configuration taken from Infusion's [Reorderer](to-do/Reorderer.md)
component:
```json5
{
events: {
onShowKeyboardDropWarning: null,
onSelect: null,
onBeginMove: "preventable",
onMove: null,
afterMove: null,
onHover: null, // item, state
onRefresh: null
}
}
```
This indicates that the Reorderer supports 6 events of the listed types, of which one, `onBeginMove` represents a
*preventable* event - a listener may countermand the `beginMove` effect by returning `true` when the event is received.
The implementor has helpfully annotated the signature which is fired by the `onHover` event - in general since
JavaScript doesn't have a type system this has to be done informally. If you have a Reorderer instance stored in a
variable named `thatReorderer`, for example, the `onSelect` event could be fired with a call like
`thatReorderer.onSelect.fire(item)`. The `fire` method of the event is a plain function which can be detached and
treated as a general callback - for example, this sequence is valid:
```javascript
var myCallback = myComponent.myEvent.fire;
myCallback(42, true);
```
In general you shouldn't fire any of a component's events unless invited to by its documentation - you may disrupt its
state. However, registering listeners to a component's events is always safe.
## Registering a listener to an event
Both as part of defaults, and also as supplied instantiation options, an Infusion component can accept a structure named
`listeners`. In the simplest form, the keys of the `listeners` structure are taken from the set of `events` present in
the component's [Grade](ComponentGrades.md), and the values are either single listener specifications or arrays of
listener specifications. A **listener specification** can take a number of forms - either being written as a simple
String or Function, or as a full JSON object. The standard way of declaring a listener using Infusion's [IoC](IoCAPI.md)
system is to supply the name of a global function using the member **`funcName`** or to supply a
[reference](IoCReferences.md) to a function handle (usually an [Invoker](Invokers.md)) somewhere in the component tree
using the member **`func`**. If your listener would like to receive different arguments than the ones that the event was
fired with, you can supply references to these using the member **`args`**. You can consult the page [Event injection
and boiling](EventInjectionAndBoiling.md) for the use of these more complex listener specifications. If you are happy
with the existing arguments you can write a simple definition as a String or Function holding the value that would have
been written in `func/funcName`. Here is a simple example of a listener definition, expanding our example from earlier:
```javascript
examples.myListener = function (number, condition) {
console.log("Event listener received number " + number + " and condition " + condition);
};
fluid.defaults("examples.eventedComponent", {
gradeNames: ["fluid.component"],
events: {
myEvent: null
},
listeners: {
myEvent: "examples.myListener"
}
});
var myComponent = examples.eventedComponent();
myComponent.myEvent.fire(97, false);
// console logs "Event listener received number 97 and condition false"
```
You should use the `String` forms for listener specifications rather than raw `Function` objects. This enables your
component's options to consist of standard JSON which is more easily stored and manipulated.
### Namespaced listeners
There are two more complex options for the keys held by listeners - firstly, the listener name may be qualified with a
**namespace** following a period character `.` - this follows the jQuery convention for namespaced events. For example,
the key `myEvent.myNamespace` could be used above - this still attaches the listener to exactly the same event, the one
named `myEvent`, but in this case the framework will make sure that only *one* listener will ever be attached to
`myEvent` which mentions the same namespace `myNamespace`. Event namespaces are useful in order to specify functional
roles for listeners, and to insist that only one listener can ever fill this role at the same time. It is a good idea to
namespace your listeners whenever you can.
Here is an example again from Infusion's Reorderer component:
```json5
{
listeners: {
"onShowKeyboardDropWarning.setPosition": "fluid.moduleLayout.defaultOnShowKeyboardDropWarning"
}
}
```
represents that the function with the global name `fluid.moduleLayout.defaultOnShowKeyboardDropWarning` should be
attached as a listener to the event `onShowKeyboardDropWarning` under the namespace `setPosition`. `setPosition` is a
name which encodes the purpose of the listener for readers of the component - it is the one to be notified whenever the
position of an item changes. Any integrator of this component can override exactly this listener by supplying the same
namespace in their own listener specification.
If one namespaced listener displaces another, the displaced listener is pushed onto a hidden stack of inactive listeners
for that namespace. If the listener which displaces it is removed (for example, through the component which registered
it being destroyed), the displaced listener will be popped back off the stack and become active again.
### Listeners to events held elsewhere
Secondly, rather than a simple string, the key in a `listeners` structure can hold any [IoC Reference](IoCReferences.md)
which resolves to an event anywhere in the component tree - that is, even one belonging to a different component. In
this case the listener on the right hand side will be attached to that event rather than one of this component's own
events. The framework will make sure to automatically deregister the listener when this component is destroyed. Many
more complex cases are possible, including the wholesale injection of events from one component to another, and the
creation of new events derived from existing ones. You can consult the page [Event injection and
boiling](EventInjectionAndBoiling.md) for more details.
### Full listener record form
In many cases, the short form above where the listener declaration just consists of a single `String` doesn't provide
enough space for all the directives that you want to supply for how the listener is notified. In this case, you can use
the long form record, where the listener record takes the form of a JSON structure with the following members (the key
for this record stays the same as above):
Member Name |
Type |
Description |
listener , func/funcName |
{String} |
This holds the actual designation of the function which is to be the listener, which was the string that consisted of
the entire "short form" for the listener definition above. This, as before, holds either the name of a global function
or an IoC reference to a function. The `func`/`funcName` form is supported for consistency with the syntax for
[Invokers](Invokers.md) and the name `listener` will be deprecated for the Infusion 2.0 release.
|
args (optional) |
{Any} |
If supplied, this structure will be used to replace the actual arguments received by the listener, rather than
necessarily receiving the exact signature fired by the firer. Any [IoC references](IoCReferences.md) or
[expanders](ExpansionOfComponentOptions.md) will be expanded at the time of invoking the listeners, with the additional
possibility of referring to the original argument list by using the special context `{arguments}`. Consult [Event
Injection and Boiling](EventInjectionAndBoiling.md) for more details of this process.
|
namespace (optional) |
{String} |
This holds the same string that would have followed the listener name after a period in the "short form" described
above. The namespace can serve three functions - i) to ensure that exactly one listener per namespace is registered with
this event firer, ii) to serve as a convenient value by which the listener can be identified for later removal by a
procedural call to `removeListener`, and iii) to allow the listener to be targeted by a *priority rule* (see the next
option for details).
|
priority (optional) |
{String|Number} |
This field allows the configurer to control the sequence in which several listeners to the same event are notified. The
recommended form of this field is either `before:otherNamespace` or `after:otherNamespace` where `otherNamespace`
represents the `namespace` of some other listener attached to this firer. The framework will sort all the listeners
attached to a single firer so that such a listener is fired immediately before or after the other target listener,
unless a further constraint positions a third listener in between them. If a group of listeners express a cyclic set of
constraints, the framework will signal an error. If there is no listener with the target namespace, the constraint is
ignored. There are other possibilities for the `priority` field which are not - more details are present in the page on
[Priorities](Priorities.md).
|
## Using events and listeners procedurally
Traditional procedural APIs corresponding to all the above declarations exist. However, these APIs, with the exception
of the `fire` method of an event, are not encouraged for typical users of the framework. For managing the lifecycle of
event firers, as well as adding and removing listeners, you are recommended to use the declarative configuration above.
### Using an event firer procedurally
Once an event firer is constructed, it can be called with the following methods (these form a stable API - but only the
`fire` method is recommended for typical users):
Method |
Arguments |
Description |
addListener |
(listener {Function|String}[, namespace {String}, priority {String|Number}]) |
Registers the supplied listener with this firer. The listener represents a function of a particular signature which is
determined between the firer and listener of an event. The namespace parameter is an optional
String which defines a key representing a particular function of the listener. At most one
listener may be actively registered with a firer with a particular namespace. If a further listener B is registered with
the same namespace as a previous one A, A will be pushed onto a hidden stack, from the top of which it will be recovered
by a call to removeListener removing B. Priorities are discussed in more detail on their own page
[Priorities](Priorities.md).
|
removeListener |
(listener {String|Function}) |
Supplies either the same listener object which was previously supplied to addListener , or else the
String representing its namespace key. The designated listener will be removed from the list of registered
listeners for this firer.
|
fire |
(arbitrary) |
Fires an event to all the registered listeners. They will each be invoked with the exact argument list which is
supplied to fire itself. If this is a preventable event, fire may return
true indicating that a listener has requested to prevent the effect represented by this event.
|
destroy |
none |
Destroys this event firer. If an event is currently in the process of firing, no further listeners will be
notified after the current listener returns. Any firing action performed in the future on this firer will be a
no-op.
|
### Constructing an event firer procedurally
The Fluid event system is operated by instances of an *event firer* which are created by a call to
`fluid.event.makeEventFirer()`. It is recommended that users don't construct event firers by hand but instead rely on
the framework's facilities for automatically constructing these given event blocks in [component
options](ComponentConfigurationOptions.md). The signature of `fluid.event.makeEventFirer` is not a stable API:
```javascript
var myFirer = fluid.makeEventFirer(options);
```
Members of the options structure supplied to fluid.event.makeEventFirer (unstable
API)
|
Option |
Type |
Description |
preventable [optional] DEPRECATED |
boolean |
If true , this event firer represents a preventable action (see Declaring an event on a component).
|
name [optional] |
string |
A name for this event firer, useful for diagnostic and debugging purposes
|