I have a Livewire page with multiple livewire nested components.
One of them has a vue component and another uses Alpine.
(So, Vue and Alpine is not used in the same component. They exist as nested components in one Laravel Component)
All is working well until I add x-on:input.debounce.250="@this.call(...)" to an input, in the component using Alpine.
If I comment out the Livewire component that contains the Vue component, all is working again.
So there is some kind of conflict when using them all together.
There is a lot of code involved. If someone could get me a hint on where to start trouble shooting this, I would be very grateful :)
Attaching the code from the Alpine component that breaks.
Context
The error I get is:
VM4533:3 Uncaught (in promise) ReferenceError: tag is not defined
at eval (eval at saferEval (alpine.js:101), <anonymous>:3:27)
at saferEval (alpine.js:101)
at Component.evaluateReturnExpression (alpine.js:1551)
at alpine.js:1518
at Array.forEach (<anonymous>)
at Component.resolveBoundAttributes (alpine.js:1500)
at Component.initializeElement (alpine.js:1419)
at alpine.js:1403
at alpine.js:1393
at walk (alpine.js:77)
VM4533:3
(function anonymous($data,$dispatch
) {
var result; with($data) { result = tag }; return result
})
The component with Alpine that breaks (but works, if I comment out the vue component)
<div>
<div x-data='{tags: @json($tags), newTag: ""}'>
<div class="w-full">
<div class="flex flex-wrap">
<template x-for="tag in tags" x-bind:key="tag">
<span class="tags-input-tag">
<span x-text="tag"></span>
<button type="button" x-on:click="tags = tags.filter(i => i !== tag)">
×
</button>
</span>
</template>
<input x-on:input.debounce.250="@this.call('search', newTag)" name="search" placeholder="Add tag..."
x-on:keydown.enter.prevent="if (newTag.trim() !== '' && !tags.includes(newTag)) {
tags = tags.concat([newTag.trim()]);
newTag = ''
}"
x-model="newTag">
</div>
</div>
<div class="flex items-center border">
@foreach($options as $option)
<button x-on:click.prevent="if (!tags.includes('{{$option}}')) {
tags = tags.concat(['{{ $option }}']);
}">{{ $option }}</button>
@endforeach
</div>
<button class="bg-aurora-green text-white rounded shadow"
x-on:click.prevent="@this.call('syncTags', tags)">Save</button>
</div>
</div>
Livewire recommends that you don't mix all three of those tools.
However, I did recently see a tweet of someone who did this successfully: https://twitter.com/asantibanez/status/1272922128300552193
I managed to make them play nice together. The trick is to never user any shorthand syntax like @click or :class. One have to use x-bind/v-bind + x-on/v-on. Otherwise all js libs will try to interpret the code.
The main problem was actually Turbolinks on top of it all. Making a full page reload whenever I visit this page - all is working.
And - yes the load order is important.
Most helpful comment
I managed to make them play nice together. The trick is to never user any shorthand syntax like @click or :class. One have to use x-bind/v-bind + x-on/v-on. Otherwise all js libs will try to interpret the code.
The main problem was actually Turbolinks on top of it all. Making a full page reload whenever I visit this page - all is working.
And - yes the load order is important.