⚠️ The contents of this repo have been migrated to theliferay/liferay-frontend-projects
monorepo and more specifically to the to theguidelines/
directory. Maintenance will continue there, and this repo will be archived (ie. switched to read-only mode). Depending on whether files have moved in the new repo, you may be able to see the current version of this page at this location.
Liferay's global event bus implementation allows developers to publish and listen to custom events from anywhere inside DXP.
In many situations you do not actually need a global event system because a more local form of communication may suffice. For example, React components often store shared state in a common ancestor, passing data down the tree via props or context, and communicating upwards using callbacks or by dispatching actions.
The Liferay event system is useful to communicate between isolated contexts (eg. widgets, iframes).
Here is a list of available functions from Liferay's global variable:
Liferay.on
Liferay.once
Liferay.onceAfter
Liferay.after
Liferay.before
Liferay.detach
Liferay.detachAll
Liferay.fire
This function subscribes a callback function to a custom event fired by this object or from an object that bubbles its events to this object.
Callback functions for events published with emitFacade = true
will receive an EventFacade
as the first argument (which should be named event
, not evt
or e
). These callbacks can then call event.preventDefault()
to disable the behaviour published to that event's defaultFn
. See the EventFacade
API for all available properties and methods. Subscribers to non-emitFacade
events will receive the arguments passed to fire()
after the event name.
Returning false
from a callback is supported as an alternative to calling event.preventDefault(); event.stopPropagation();
. However, it is recommended to use the event methods whenever possible.
const someEventCallback = (event) => {
// This callback will be called when "someEvent" were triggered somewhere
};
Liferay.on('someEvent', someEventCallback);
Listen to a custom event one time.
This is the equivalent to on
function except the listener is immediately detached when it is executed.
const someEventCallback = (event) => {
// Called only once, no need to call `detach()`.
};
Liferay.once('someEvent', someEventCallback);
Listen to a custom event one time after other handlers have executed.
This is the equivalent to after
except the listener is immediately detached when it is executed.
const someEventCallback = (event) => {
// Do something one time only after all other handlers for "someEvent" have executed
};
Liferay.onceAfter('someEvent', someEventCallback);
Subscribe to a custom event after other handlers have executed.
The supplied callback will execute after any listeners add via the subscribe method, and after the default function, if configured for the event, has executed.
const someEventCallback = (event) => {
// Do something after all other handlers for "someEvent" have executed
};
Liferay.after('someEvent', someEventCallback);
Executes the global event callback before a DOM event, custom event or method. If the first argument is a function, it is assumed the target is a method.
Detach one or more listeners the from a specified event
function doSomething(event) {
// Do something here when 'something' happens
}
Liferay.on('something', doSomething);
Liferay.detach('something');
Removes all listeners from the specified event. If the event type is not specified, all listeners from all hosted custom events will be removed.
Fire a custom event by name. The callback functions will be executed from the context specified when the event was created, and with the following parameters.
The first argument is the event type, and any additional arguments are passed to the listeners as parameters. If the first of these is an object literal, and the event is configured to emit an event facade, that object is mixed into the event facade and the facade is provided in place of the original object.
If the custom event object hasn't been created, then the event hasn't been published and it has no subscribers. For the sake of performance, we immediately exit in this case. This means the event won't bubble, so if the intention is that a bubble target be notified, the event must be published on this object first.
Liferay.fire('someEvent', {
myCustomProperty: 'myValue'
});
The best practice number #1 is using Liferay's namespace utilities (Liferay.Util.ns
) when possible. Like Liferay.Util.ns(myWidgetNamespace, 'nameOfMyCustomEvent')
. For scoping the global name of the event. It will prevent you from listening to generic events which can be fired in different widgets for which you may not be responsible.
Additional information: When using simpler ES6 class components, we could just extend to PortletBase and use this.ns
function.
Wrong:
Liferay.fire('CLOSE_MODAL', {
id: 'myId'
});
Correct:
// See: https://github.com/liferay/liferay-portal/blob/master/modules/apps/frontend-js/frontend-js-web/src/main/resources/META-INF/resources/liferay/util/ns.es.js
import {ns} from 'frontend-js-web';
Liferay.fire(ns(portletNamespace, 'CLOSE_MODAL'), {
id: 'myId'
});
// When portletNamespace not available:
Liferay.fire('commerce:CLOSE_MODAL', {
id: 'myId'
});