Angular NGXS and WebSockets with Laravel backend

Hopefully you have already worked with the exciting state management system for Angular 2+ NGXS. I found that there isn’t a lot of content online about NGXS +WebSocket + Laravel. So here I am, I would like to share how to add WebSocket integration for your Angular App if you are using Laravel as backend.

Let’s get started with a simple scheme, which explains how it works in general:

Let’s go deep into details:

  1. Client app establishes WebSocket connection to our NodeJs/Express server with channelName and clientID (random unique string):
connectToSocket() {
const currentUser = JSON.parse(localStorage.getItem('currentUser'));
const clientId = uuid.v4();
this.store.dispatch(new SetClientID(clientId));
if (currentUser && currentUser.token) {
this.store.dispatch(
new ConnectWebSocket({
url: `${environment.nodeServerIp}?channelName=private-budget-${
this.id
}&token=${currentUser.token}&email=${
currentUser.username
}&clientId=${clientId}`,
}),
);
}
}

2. The client sends typical REST requests to Laravel with clientID and channelName in a payload.

Patch request to Laravel REST server

3. Laravel extracts clientId and channelName and fires the Event class, which sends a message to Redis channel

event(new UpdateBudgetEvent($clientId, $budgetId, $budgets));
**** UpdateBudgetEvent class ****
class UpdateBudgetEvent extends Event implements ShouldBroadcast
{
....
// broadcastOn method will send to Redis all PUBLIC properties
public function broadcastOn()
{
$data['type'] = '[App] SocketUpdateBudget';
$data['data'] = $this->budget;
$this->data = json_encode($data);
return new PrivateChannel('budget-' . $this->budgetId);
}

4. Nodejs application listens to Redis channel and when a message comes, NodeJs sends a message to the relevant client in the right channel

redis.on('pmessage', (pattern, channel, message) => {
message = JSON.parse(message);
wss.clients.forEach((client) => {
// Check channel
if (client.channelName == channel) {
// Check client
if (client.clientId != message.data.clientId) {
client.send(message.data.data);
}
}

5. NGXS will automatically get this message (from WebSocket frame) and dispatch the action which will adjust your state

// app.actions.ts
export class SocketUpdateBudget {
static readonly type = '[App] SocketUpdateBudget';
constructor(public data: any[]) {}
}
// app.state.ts
@Action(SocketUpdateBudget)
socketUpdateBudget(
ctx: StateContext<AppStateModel>,
data: SocketUpdateBudget,
) {
const state = ctx.getState();
// DO your logic with state here
}

And that’s actually it, pretty straightforward. Hope it any Angular/NGXS developers out there.

Final result:

Demo

If you want to see more you can also play around at myracle.co.

Hope it was useful reading, don’t hesitate if you have questions or comments and don’t forget to 👏 if this article saves some time in your coding path…