Livewire: Combining Alpine, Vue and Livewire, breaks Alpine.

Created on 28 May 2020  路  3Comments  路  Source: livewire/livewire

Description

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.

Steps to reproduce

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

  • Livewire version: 1.1.0
  • Laravel version: 7.12.0
  • Alpine: 2.3.3
  • Vue 2.6.11
  • Livewire-vue js plugin 0.2.0

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)">
                            &times;
                        </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>

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.

All 3 comments

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.

Was this page helpful?
0 / 5 - 0 ratings