如何在Laravel Livewire的wire:click.prevent中在新标签中打开链接

huangapple go评论86阅读模式
英文:

How to Open Links in New Tabs with Laravel Livewire's wire:click.prevent

问题

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!

英文:

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:

&lt;a href=&quot;{{ route(&#39;inventory.show&#39;) }}&quot; wire:click.prevent=&quot;$emit(&#39;navigate&#39;, {&#39;page&#39;:&#39;inventory.show&#39;, &#39;route&#39;:&#39;{{ route(&#39;inventory.show&#39;) }}&#39;})&quot; class=&quot;nav-link&quot;&gt;Link&lt;/a&gt;

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!

答案1

得分: 1

以下是您要求的翻译部分:

主要的挑战在于 wire:click.prevent 属性会阻止 <a> 标签的默认行为,即在新标签页中打开链接。这意味着即使您使用自定义 JavaScript 来检测 CMD 或 Ctrl 按键,wire:click 函数仍将被执行,链接不会在新标签页中打开。

为了解决这个问题,我们可以使用一个自定义指令来覆盖 wire:click.prevent 属性的行为。该指令将检查用户是否按下 CMD 或 Ctrl 键,如果是,它将在不执行 wire:click 函数的情况下在新标签页中打开链接。

以下是代码实现:

<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>

该指令首先检查用户是否按下 CMD 或 Ctrl 键。如果是,它将阻止 <a> 标签的默认行为并在新标签页中打开链接。如果用户没有按下 CMD 或 Ctrl 键,则 wire:click 函数将如常执行。

要使用这个指令,只需将 wire:custom-directive 属性添加到您想要在新标签页中打开的 <a> 标签上。例如:

<a href="{{ route('inventory.show') }}" wire:custom-directive>
  Link
</a>
英文:

The main challenge here is that the wire:click.prevent attribute prevents the default behavior of the <a> 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

&lt;livewire:custom-directive wire:click.prevent=&quot;openLinkInNewTab&quot;&gt;
  &lt;a href=&quot;{{ route(&#39;inventory.show&#39;) }}&quot;&gt;Link&lt;/a&gt;
&lt;/livewire:custom-directive&gt;

&lt;script&gt;
  Livewire.directive(&#39;custom-directive&#39;, {
    bind: function (el, binding, vnode) {
      el.addEventListener(&#39;click&#39;, function (event) {
        if (event.ctrlKey || event.metaKey) {
          event.preventDefault();
          window.open(binding.value);
        }
      });
    },
  });
&lt;/script&gt;

This directive will first check if the user is pressing CMD or Ctrl. If they are, it will prevent the default behavior of the <a> 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 <a> tag that you want to open in a new tab. For example:

&lt;a href=&quot;{{ route(&#39;inventory.show&#39;) }}&quot; wire:custom-directive&gt;
  Link
&lt;/a&gt;

huangapple
  • 本文由 发表于 2023年8月4日 21:15:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76836287.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定