Ben Taylor's avatar

How to trigger button action without firing wire:naviation on nested button

Hi everyone,

I'm in the process of migrating my project from using Vue3 (not inertia) to livewire 3.

I have run into an issue on my product card component. It is essentially a standard product card showing product name, image price etc. The card is wrapped in an achor tag to direct customers to the product page when clicking the card.

Within the product card is an add to wishlist button that should trigger an action to do as such within the livewire component. I have added .prevent on the livewire click handler to prevent the anchor tag from being triggered. This works fine when my anchor tag is a regular anchor tag. But I want to use the new 'wire:navigate' attribute on my anchor tag. When I add this, the wishlist button click no longer prevents the anchor tag from firing.

In my developer tools network tab I can see it making 2 requests. First one is the anchor route, the second is the livewire update route. Without wire:navigate, only the livewire update route is requested.

So sure, I can just not use wire:navigate and all is fine and dandy. But I really want the additional stuff that wire:navigate does. Am I missing something, or is this a bug in livewire?

0 likes
5 replies
LaryAI's avatar
Level 58

To trigger the button action without firing the wire:navigate on the nested button, you can use the wire:click.prevent directive on the button element. This will prevent the default behavior of the button and stop the event from propagating to the parent anchor tag.

Here's an example of how you can modify your code:

<div>
    <a href="{{ route('product.show', $product) }}" wire:navigate>
        <!-- Product Card Content -->
        <h3>{{ $product->name }}</h3>
        <img src="{{ $product->image }}" alt="{{ $product->name }}">
        <p>{{ $product->price }}</p>
    </a>
    <button wire:click.prevent="addToWishlist({{ $product->id }})">Add to Wishlist</button>
</div>

In this example, the wire:click.prevent directive is added to the button element, which will prevent the default click behavior and stop the event from bubbling up to the parent anchor tag.

Make sure to replace addToWishlist with the actual method name in your Livewire component that handles the wishlist functionality. Also, pass any necessary parameters to the method, such as the product ID in this case.

By using wire:click.prevent, you can trigger the button action without interfering with the wire:navigate behavior on the parent anchor tag.

Ben Taylor's avatar

Wow, that AI reply really missed the boat. For one, I am already doing what it suggested. And two, the html example doesn't even represent what I described. I am talking about a nested button within the anchor tag, not one below the anchor tag. Thanks for absolutely nothing Lary!

AinaRAKOTOMALALA's avatar

I have the same problem. I didn't find any solution so i just remove the wire:navigate

Ben Taylor's avatar

@AinaRAKOTOMALALA I did too, but it isn't really the ideal solution. I've parked Livewire for now and will wait to see if they fix these bugs before I integrate it properly.

rohankhatri's avatar

@ben taylor @ainarakotomalala

The new wire:navigate works on mousedown event. So, i made it working by using alpinejs stopPropogating event on Cart button's click event.

Here is the working example.

<a wire:navigate href="{{ route('products.show', $product) }}">
    <div>
        <div>
            Name
            Price
        </div>

        <button @mousedown.stop="$wire.addToCart('{{ $product->id }}')">
            Add to Cart
        </button>
    </div>
</a>

Please or to participate in this conversation.