Support Wire Drupal

Fund development, features & content

Sponsor

Events

Handling component events

Wire components can communicate with each other through a global event system. As long as two Wire components are living on the same page, they can communicate using events and listeners.

Firing Events

There are a few ways to fire events from Wire components.

From The Template


<button wire:click="$emit('nodeAdded')">

From The Component

$this->emit('nodeAdded');

From Global JavaScript


<script>

  Wire.emit('nodeAdded')

</script>

Event Listeners

Event listeners are registered in the $listeners property of components.

Listeners are a key -> value pair where the key is the event to listen for, and the value is the method to call on the component.

class ShowNodes extends WireComponentBase {

  public int $nodeCount;
  
  protected $listeners = ['nodeAdded' => 'updateNodeCount'];
  
  public function updateNodeCount() {

    $this->nodeCount = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->getQuery()
      ->accessCheck(TRUE)
      ->count()
      ->execute();
    }
}

Now when any other component on the page emits a nodeAdded event, this component will pick it up and fire the updateNodeCount method on itself.

If the name of the event and the method you're calling match, you can leave out the key. For example: protected $listeners = ['nodeAdded']; will call the nodeAdded method when the nodeAdded event is emitted.

If you need to name event listeners dynamically, you can substitute the $listeners property for the getListeners() protected method on the component:

class ShowNodes extends WireComponentBase {

  public int $nodeCount;
  
  protected function getListeners() {
    return ['nodeAdded' => 'updateNodeCount'];
  }
  
}

The getListeners() method will only dynamically generate the names of listeners when the component is mounted. Once the listeners are setup, these can't be changed.

Passing Parameters

You can send parameters with an event emission.

$this->emit('nodeAdded', $node->id());
class ShowNodes extends WireComponentBase {

  public int $nodeCount;

  public int $latestAddedNodeId;

  protected $listeners = ['nodeAdded' => 'incrementNodeCount'];

  public function postAdded($nodeId) {

    $this->latestAddedNodeId = $nodeId;

    $this->nodeCount = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->getQuery()
      ->accessCheck(TRUE)
      ->count()
      ->execute();
  }

}

Scoping Events

Scoping To Parent Listeners

When dealing with nested components, sometimes you may only want to emit events to parents and not children or sibling components.

In these cases, you can use the emitUp method.

$this->emitUp('nodeAdded');

<button wire:click="$emitUp('nodeAdded')">

Scoping To Components By Name

You may only want to emit an event to other components of the same type(by name).

In these cases, you can use emitTo:

$this->emitTo('counter', 'nodeAdded');

<button wire:click="$emitTo('counter', 'nodeAdded')">

With above, if the button is clicked, the "nodeAdded" event will only be emitted to components with ID counter.

Scoping To Self

You may only want to emit an event on the component that fired the event.

In these cases, you can use emitSelf:

$this->emitSelf('nodeAdded');

<button wire:click="$emitSelf('nodeAdded')">

With above implementation, if the button is clicked, the "nodeAdded" event will only be emitted to the instance of the component that it was emitted from.

Listening For Events In JavaScript

Wire allows you to register event listeners in JavaScript like so

<script>

  document.addEventListener("DOMContentLoaded", () => {
    
    Wire.on('nodeAddedNotify', nodeId => {
      alert('A new Node entity has been created with the id of: ' + nodeId);
    })
    
  });
  
</script>

Dispatching Browser Events

Fire browser window events like so

$this->dispatchBrowserEvent('node-added', ['newName' => $this->title]);

And listen for this window event with JavaScript

window.addEventListener('node-added', event => {
  alert('A new Node entity has been created with the Title of: ' + event.detail.nodeTitle);
})

If you have AlpineJS, it allows you to easily listen for these window events within your HTML.

E.g: Show a message when the Event is dispatched:

<p
  x-data="{ open: false }"
  @node-added.window="open = true"
  x-show="open"
  style="display: none;"
>A new Node entity has been created</p>