Get Started With Pusher: Client Events

In this series, we’ve been learning about Channels from Pusher, a platform that allows you to give your users the seamless real-time experience they want.

Get Started With Pusher: Client Events

Throughout this series, we have looked strictly at server events—events that originate on the server—but we also have the ability to trigger events from the client. These are called client events, and they provide a different service than server events because some actions may not need validation or persistence.

Client events have several restrictions that your application must adhere to in order to use them. The most notable are:

  • Client events must be enabled through your Channels application’s dashboard.
  • Client events can only be issued on private and presence channels.
  • They are not delivered to the client that initiates the event.
  • They are limited to no more than ten messages per second per client.

Triggering Client Events

We’ll look at an example of client events by adding a link to our private chat app that sends an alarm to all the connected clients. Client events are triggered from the object returned by the Pusher library’s subscribe() method. We use this method inside the ChannelsChat Vue.js component with the following code:

let channel = pusher.subscribe('private-chat');

Triggering a client event is very similar to triggering a server event. You use channel.trigger() to initiate the event and pass the event name and event data to it, like this:

channel.trigger('client-send-alarm', { message: 'Alarm!' });

Client event names must begin with client-, as shown in this code. The remainder of the name is completely up to you. The event data is nothing more than a normal JavaScript object that contains the properties (and their values) you want to send with the event.

Modifying the Chat Application

The chat application’s channel object resides inside the ChannelsChat Vue.js component—that’s where we create the object and set up the listener for the send-message event. We can restructure this component so that it provides a mechanism for triggering client events.

The first thing we need to do is store our channel object as instance data so that we can reference it throughout the entire component. We’ll do this by adding a channel property to our component, like this:

data() {
    return {
        messages: [],
        channel: null
    }
}

Then we’ll change the created() hook so that we store our channel object in the new channel property instead of the channel variable.

// let channel = pusher.subscribe('private-chat'); // old code
this.channel = pusher.subscribe('private-chat');

Just remember that this change requires us to prefix the previous uses of channel with this.

Triggering a Client Event

Now let’s add a method that will trigger a client event. Let’s call it trigger(), and its code will look like the following:

methods: {
    trigger(eventName, message) {
        this.channel.trigger(eventName, { message });
    }
}

It accepts the event name and the message to include with the event and passes that data onto this.channel.trigger(), thus triggering the client event.

The user primarily interacts with the MessageSend component because it contains the UI for entering and sending messages. So we’ll pass the trigger() method as a prop to MessageSend, like this:

<message-send :trigger="trigger" />

Listening for the Client Event

The last thing we need to do in this component is listen for the client-send-alarm event. Listening for client events is almost identical to listening for server events—the only difference is the data we pass to the bind() method. Add the following as the last line of the created() hook:

this.channel.bind('client-send-alarm', (data) => alert(data.message));

For this event, we don’t push the provided message to the chat screen. Instead, we simply display the provided message in an alert box.

Wiring Up the UI

In the MessageSend component, let’s first add the trigger prop to the component.

props: ['trigger']

Let’s then add the new alarm link after the Send button.

<div class="col-sm-2">
    <button type="submit" class="btn btn-primary">Send</button>
</div>
<div class="col-sm-2">
    <a href="#" @click.prevent="sendAlarm">Alarm!</a>
</div>

The link’s click event is bound to the sendAlarm() method, which we’ll add to the component’s methods declaration. Here is this method’s very simple code:

methods: {
    // sendMessage() here
    
    sendAlarm() {
        this.trigger('client-send-alarm', 'Alarm!');
    }
}

The sendAlarm() method simply calls trigger(), passing client-send-alarm as the event name and Alarm! as the message.

Testing the Changes

In order to see the results of our code changes, you’ll need two clients connected to the chat app. While that may seem obvious, there is a very good reason for having two clients open: the client that initiates the event does not receive the event.

So, with two clients open, click the Alarm! link in one client, and you will see the event handled in the other client, as shown here:

Get Started With Pusher: Client Events

The client on the left triggered the event, and you can see it handled in the client on the right.

Conclusion

It goes without saying that the majority of events used in Channels-powered applications are server events, but there are some cases where you may want to initiate an event that doesn’t need server-side validation or persistence. With Channels from Pusher, it is incredibly easy to trigger and listen for client events!