Component Events
Component events (also known as DOM events) are similar to page events, except that they are fired by components on a page (or other container).
A component event listener can have any name, and is generally associated to a component event property via the binding expression on the component markup. Component event listeners are defined in the Page (or container) module under the eventListeners
property, much like other Visual Builder events. For example, an event listener for the selectionChange
event for the <oj-tab-bar> component can be defined within the eventListeners
section as:
"eventListeners": {
"onSelectionChange": {
"chains": [
{
"chainId": "respondToChange",
"parameters": {
"text": "{{ $event.detail.value }}"
}
}
]
}
}
Component event listeners are called in the same way as page lifecycle event listeners. There can be more than one listener. When there is more than one, they run in parallel.
To reference an event listener from a component, you can use the
$listeners.
eventListenerName implicit object. For
example:
<oj-select-single ... on-selection-change="[[$listeners.onSelectionChange]]"
Component Event Objects
Within the context of component event listeners, there are three implicit objects.
-
$event
: The event payload sent by the component. -
$current
: This represents the second parameter passed to the handler, if any. For JET, this can be either the$current
binding variable, or the$data
variable if$current
does not exist in the component context. -
$bindingContext
: represents the third parameter passed, if any. For JET, this is the (Knockout) view model, and it will therefore contain the$current
or$data
variable as a property.
These variables do not exist outside the listener context. In other words, you can reference these in the listener declaration, but you cannot reference them in the called action chain; any values needed in these variables must be passed explicitly to the action chain as arguments (chain variables).
These three variables represent the arguments passed to the listener, and are not directly tied to specific JET values. Their meaning could be different depending on the context.
For example, if using an event listener within an <oj-list-item>
item, the value of $current
could be different whether you are using the item.renderer
attribute or the itemTemplate
slot to display the item.
-
Within an
item.renderer
script, JET does not define $current, so instead passes $data as the second argument, so the Visual Builder $current is JET/Knockout $data. In some JET contexts, like anitem.renderer
script, you will also need to prefix Visual Builder listeners with (Knockout) $parent in the HTML. -
Within an
itemTemplate
slot, JET defines$current
, and passes that, so Visual Builder $current is JET $current.
To determine whether JET $current
exists for your use case., refer to the JET documentation for the component to which you are adding a listener.
Additionally, the developer could decide to pass their own custom object for the parameters. In the example below, the listener is wrapped, so Visual Builder $current
is "some string", and Visual Builder $bindingContext
is undefined.
<oj-button on-click="{{ function(event, current, bindingContext) { $page.listeners.someListener(event, "some string") } }}">
Click Me!
</oj-button>
Component Event Listener "preventDefault" Property
Component event listeners have an additional preventDefault
property, which can be used to prevent the normal DOM event handling from being executed.
This example uses an expression to check the payload of the event to stop propagation:
"eventListeners": {
"customEventTwo": {
"chains": [
{
"actionsId": "handleEventInMod2PageChain",
"parameters": {
"eventPayload": "{{ $event }}"
},
}
],
"preventDefault": "{{ $event.type === 'info' }}"
}
Component Event Listener "asyncBehavior" Property
Some components such as the JET table support events that accept async event listeners, where the event accepts a Promise. This allows the component that fired the event to cancel it asynchronously, if needed. The Promise provided by Visual Builder event listeners can also be resolved or rejected within Visual Builder based on the action chain's behavior.
To opt in to the async behavior for a component event, the eventListeners
property asyncBehavior
must be set to "enabled"
. The default value for this property is "disabled"
. Before implementing action chain logic, refer to the component docs to make sure you understand the implications of enabling async behavior.
ojBeforeRowEditEnd
event, with the asyncBehavior
property set to "enabled"
within the eventListeners
property:{
"eventListeners": {
"tableBeforeRowEdit": {
"asyncBehavior": "enabled",
"chains": [
{
"chainId": "beforeRowEditChain",
"parameters": {
"rowIndex": "{{$event.detail.rowContext.status.rowIndex}}"
}
}
]
}
}
}
ojBeforeRowEditEnd
event in the preceding example can be configured as:<oj-table scroll-policy="loadMoreOnScroll"
id="oj-table-1"
class="oj-flex-item oj-sm-12 oj-md-12"
edit-mode="rowEdit"
selection-mode='{"row": "single"}'
data="{{ $page.variables.productsADP }}"
scroll-policy-options.fetch-size="3"
columns="{{ $page.functions.columnsArray }}"
on-oj-before-row-edit="[[$listeners.table1BeforeRowEdit]]">
...
</oj-table>