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
will be automatically dispatched as the Magento event
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.
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: