Skip to content

Emit messages

Subscribing to messages

We saw earlier that components can $emit messages.
This is a publish/subscribe system built into Magewire. If you know Magento event/observers, also known as event/subscribers in JavaScript, you will feel right at home.

When a message is emitted, the first argument is the name of a public method on the Magewire component.
However, not every public method can be called this way. Messages can only be emitted to methods listed in a protected $listeners array.
If this is the case, the method will be invoked by Magewire when a component emits a message with a matching name, passing along any arguments.

Here an example of a component that listens to doSomething messages:

class MyComponent extends \Magewirephp\Magewire\Component
{
    protected $listeners = ['doSomething'];

    public function doSomething($value)
    {
        // Inside the callback
    }
}

Calling a method with a different name

If the emitted message name is not suitable as a method name, the $listeners property can also be used as an associative array.
The array keys are the emitted message names, and the values are the names of the methods to be called.

    protected $listeners = [
        'shipping_method_selected' => 'refresh',
        'coupon_code_applied' => 'refresh',
        'coupon_code_revoked' => 'refresh'
    ];

Emitting messages

A message can be emitted in several ways, depending on context.

From PHP (only during subsequent requests):

class MyOtherComponent extends \Magewirephp\Magewire\Component
{
    public function myAction()
    {
        $payload = ['id' => 69];
        $this->emit('doSomething', $payload);

        // or, to target a specific block
        // $this->emitTo('some.block.name', 'doSomething', $payload);
    }
}

Note that emit only works during subsequent requests.

Emitting messages with a Magewire directives:

<button wire:click="$emit('doSomething', {result: result, foo: 'bar', confirmed: true})">Click me</button>

<!-- or, to target a specific block: -->

<button wire:click="$emitTo(
    'some.block.name',
    'doSomething',
    {result: result, foo: 'bar', confirmed: true}
)">Click me</button>

Emitting messages from vanilla JavaScript:

Magewire.emit('doSomething', {value: payload})

// or, to target a specific block:

Magewire.emitTo('some.block.name', 'doSomething', {value: payload})

Magento Event Interop

Every message that is emitted in Magewire is also dispatched as a Magento event.
The event name is the emit action, prefixed with magewire_.

For example, the emitted message

$emit('doSomething', {result: 42, confirmed: true})

will be automatically dispatched as the Magento event

$eventManager->dispatch('magewire_doSomething', ['result' => 42, 'confirmed' => true])

Livewire style emit payloads

In Livewire, emit parameters are passed as individual values instead of an associative array.
The Livewire syntax can also be used in Magewire, but it is discouraged because it doesn't work well with the Magento event interoperability.

// Magewire syntax:
$this->emit('doSomething', ['result' => $result, 'is_confirmed' => $isConfirmed]);

// Livewire syntax:
$this->emit('doSomething', $result, $isConfirmed);
The same applies to emits on the frontend:
<button wire:click="$emit('doSomething', {result, isConfimed: true})">Magento syntax</button>
<button wire:click="$emit('doSomething', result, true)">Livewire syntax</button>

A note on coupling

One of the key advantages of the event/observer pattern (a.k.a. pub/sub or by other names) is that the publisher of the event is decoupled from any observers.
This is not the case for emitTo, where a specific target name is specified.

Because of this, emitTo is not an implementation of the event/observer pattern, but rather a form of message passing, more like calling a method on a specific class instance, for example $object->doSomething().
This is fine, but it is good to be mindful of the increased coupling, which can lead to more brittle code if used too much.

Listening to messages in JavaScript

As documented in the Livewire documentation, it is possible to listen to messages emit by components in JavaScript:

Magewire.on(
    'foo',
    event => {
        console.log(event.bar);
    }
);