# Events
# How to send events to users?
Let's look at the example of a new alert notification.
Create a listener for the entity_post_save
event with the hint XF\Entity\UserAlert
.
Then create a new broadcasting event with UpdateAlerts
name in YourAddon/Broadcasting/Events
folder:
namespace YourAddon\Broadcasting\Events;
use BS\XFWebSockets\Broadcasting\Event;
use BS\XFWebSockets\Broadcasting\UserChannel;
use XF\Entity\UserAlert;
class UpdateAlerts implements Event
{
public UserAlert $fromAlert;
/**
* Event constructor.
* Save the alert from which we should load new alerts.
*
* @param \XF\Entity\UserAlert $fromAlert
*/
public function __construct(UserAlert $fromAlert)
{
$this->fromAlert = $fromAlert;
}
/**
* The channels to which the event will be broadcast.
*/
public function toChannels(): array
{
return [
// Broadcast to the alert recipient's private channel.
new UserChannel($this->fromAlert->alerted_user_id)
];
}
/**
* The data to be broadcast.
*/
public function payload(): array
{
return [
'from_alert_id' => $this->fromAlert->alert_id
];
}
/**
* Event name.
* Optional method.
* By default, the name of an event is its class.
*/
public function broadcastAs(): string
{
return 'UpdateAlerts';
}
}
Now we can broadcast this notification in the listener we created:
use BS\XFWebSockets\Broadcast;
use XF\Entity\UserAlert;
public static function postSaveUserAlert(UserAlert $alert)
{
if (! $alert->isInsert()) {
return;
}
Broadcast::event(
'YourAddon:UpdateAlerts',
$alert
);
}
Users will now receive an UpdateAlerts
event with the from_alert_id
parameter on every alert.
# How to handle events?
Let's look at an example of handling the UpdateAlerts
event we just created.
Create a new template modification to import watch.js
file:
- Template:
helper_js_global
- Modification key:
your_adddon_helper_js_global_watch_js
- Search type: Simple replacement
- Find:
<!--XF:JS-->
- Replace:
$0
<xf:if is="$xf.visitor.user_id">
<xf:js src="your_addon/watch.js" min="1" />
</xf:if>
Create a watch.js
in the js/your_addon
folder with the following content:
!function ( $, window, document ) {
"use strict";
XF.RealTimeAlerts = $.extend(XF.RealTimeAlerts || {}, {
init () {
/*
* Listen to the `UpdateAlerts` event on the `visitor` channel.
* The `visitor` channel is created automatically when the user is logged in.
*
* getWebsocketsPromise() is a function that returns a promise
* that resolves when the WebSockets connection is established and you can subscribe to channels.
* It resolves { manager: XF.EchoManager, echo: XF.Echo }.
*
* ?. is the optional chaining operator, help to avoid errors when user has no permission to use WebSockets.
*/
window.getWebsocketsPromise?.().then(( { echo, manager } ) => {
manager.channels['visitor']
.listen('UpdateAlerts', XF.proxy(this, 'updateAlerts'))
})
},
updateAlerts ( { from_alert_id } ) {
// Send a request to the server to get new alerts.
}
})
$(document).ready(() => XF.RealTimeAlerts.init())
}
(window.jQuery, window, document);