Livewire: Using wire:click inside vue component

Created on 21 Aug 2019  路  3Comments  路  Source: livewire/livewire

Describe the bug
I am trying to use wire:click inside a Vue component:

Inside my Livewire blade component: document-viewer.blade.php

<div @click="$modal.show('test')">Documents:</div>
<modal name="test">
    @foreach($documents as $document)
        <a wire:click="changeDocument('{{ $document['id'] }}')">{{$document['original_name']}}</a><br/>
    @endforeach
</modal>

Now the modal will open fine, but whenever I click on any anchor tag with the wire:click, nothing happens.

If I move the foreach code outside of the modal, the wire:click works fine.

Currently, the changeDocument() method should simple dump:

public function changeDocument(int $documentId)
{
    dd($documentId);
}

Expected behavior
I expect that I can use the wire:click method inside my vue modal component.

Additional context
This is my app.js file:

window.Vue = require('vue');
import vmodal from 'vue-js-modal'

Vue.use(vmodal, {
    dialog: true
});

I am using this Vue modal package: Vue-js-modal

Most helpful comment

When Livewire is crawling the DOM, if it encounters a Vue component, it will skip it's contents.

This is because LIvewire AND Vue can't co-exist in that way. They both want control of the DOM. So Livewire gives up control of the DOM of any Vue component.

I recommend you use Blade for a modal component.

All 3 comments

I have a feeling this is expected behaviour as is stands.
It appears the wire:click handler is not getting registered again (which it usually does) if it is within Vue code.
In the docs https://livewire-framework.com/docs/custom-javascript/ it only show the wire:click outside the VueJS element.

It goes on to say

Livewire will listen for "input" events emitted from the Vue component, and pass down "value" properties just like Vue does. It just works.

But I don't think that extends to DOM events...

When Livewire is crawling the DOM, if it encounters a Vue component, it will skip it's contents.

This is because LIvewire AND Vue can't co-exist in that way. They both want control of the DOM. So Livewire gives up control of the DOM of any Vue component.

I recommend you use Blade for a modal component.

I have a Vue instance attached to a high-level wrapper element, surrounding the entire page, in a master layout file. This was so we could easily drop in components around the site in various places, and it would just work. Everything is "inside" Vue. Probably wasn't a good idea, but right now I'm stuck with it.

The only widespread Vue component is a shopping cart, in the header. The vast majority of our pages have no actual Vue usage in the <main> content area at all.

I was hoping to build some Livewire components that would get rendered in the <main> area of a few pages. But my wire:click handlers aren't doing anything. I'm pretty sure it's because the entire page is still part of the Vue instance element, would that be right?

I sure wish there was a way I could tell Live wire "yeah ok, I know this whole page is managed by Vue, but trust me I'm not actually _using_ Vue in this particular content area at all, you can safely still wire up and manage this area of the dom with no conflicts."

Is that at all possible?

<head>
    @livewireStyles
</head>
<body>
<div id="app">
    <header>
        <some-vue-component></some-vue-component>
    </header>
    <main>
        @livewire('my-livewire-component')
    </main>
</div>

<script>
new Vue({el: '#app'});
</script>
@livewireScripts
</body>

I'm looking for a way to force it. _Just trust me, VueJS will not stomp on your dom changes here, do your thing._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

devscript-abdo picture devscript-abdo  路  3Comments

cloudstudio picture cloudstudio  路  3Comments

austenc picture austenc  路  3Comments

mokhosh picture mokhosh  路  4Comments

cao-minh-duc picture cao-minh-duc  路  4Comments