1

I'm using the wire:click.prevent attribute to navigate inside the app by dynamically loading components using $emit inside the click attribute. For example:

<a href="{{ route('inventory.show') }}" wire:click.prevent="$emit('navigate', {'page':'inventory.show', 'route':'{{ route('inventory.show') }}'})" class="nav-link">Link</a>

Everything works well, and the navigate function replaces the current content with the content of the page passed in the parameters.

Now, I want to open the link in a new tab if the user keeps pressing the CMD (or Ctrl) button on the keyboard, which can be easily achieved via JavaScript in a normal scenario.

The main challenges are:

  1. By using wire:click.prevent, I can't directly control the way event.preventDefault() is injected into the code, so setting a custom rule to prevent or allow it becomes tricky.
  2. Even if I remove the prevent attribute and use custom JavaScript to detect CMD or Ctrl presses, how do I avoid executing the function in the wire:click while still opening the link in a new tab?

Any help or suggestions on how to achieve this behavior would be greatly appreciated. Thank you!

stefano di luca
  • 147
  • 1
  • 10

1 Answers1

1

The main challenge here is that the wire:click.prevent attribute prevents the default behavior of the tag, which is to open the link in a new tab. This means that even if you use custom JavaScript to detect CMD or Ctrl presses, the wire:click function will still be executed and the link will not open in a new tab.

To solve this, we can use a custom directive that will override the behavior of the wire:click.prevent attribute. This directive will check if the user is pressing CMD or Ctrl, and if they are, it will open the link in a new tab without executing the wire:click function.

Here's code implementation

<livewire:custom-directive wire:click.prevent="openLinkInNewTab">
  <a href="{{ route('inventory.show') }}">Link</a>
</livewire:custom-directive>

<script>
  Livewire.directive('custom-directive', {
    bind: function (el, binding, vnode) {
      el.addEventListener('click', function (event) {
        if (event.ctrlKey || event.metaKey) {
          event.preventDefault();
          window.open(binding.value);
        }
      });
    },
  });
</script>

This directive will first check if the user is pressing CMD or Ctrl. If they are, it will prevent the default behavior of the tag and open the link in a new tab. If the user is not pressing CMD or Ctrl, the wire:click function will be executed as normal.

To use this directive, you would simply add the wire:custom-directive attribute to the tag that you want to open in a new tab. For example:

<a href="{{ route('inventory.show') }}" wire:custom-directive>
  Link
</a>
Ghulam Farid
  • 470
  • 4
  • 10