Accudio / async-alpine

Async Alpine brings advanced code splitting and lazy-loading to Alpine.js components!
https://async-alpine.dev
Apache License 2.0
152 stars 12 forks source link

Cannot reference "$wire" outside a Livewire component #28

Closed JohnnyMaynne closed 9 months ago

JohnnyMaynne commented 1 year ago

Laravel v9.52.0 Livewire v2.12.0 Alpine js v3.10.3 Async-alpine v1.0.0 Vite v3.2.5

When I try to use the $wire object, I get an error . Sample code below.

Component js:

image

Register js components:

image

Blade component:

image

Error:

image image
Accudio commented 1 year ago

Hey!

I'm afraid I have no experience with Livewire so I'm not in a good position to be able to investigate this at the moment.

Would you be able to put together an example repo that's as simple as possible? Just the bare minimum required to replicate this issue without any extra libraries or anything.

That would be very helpful for if I get the time to look into this or if someone else with some Livewire knowledge wants to help.

JohnnyMaynne commented 1 year ago

I will try to restore the problem in the demo repository in the coming days 👍🏻

iniznet commented 9 months ago

To make this issue not stale, $wire only works within an AlpineJS component. Reference: https://laravel-livewire.com/docs/2.x/alpine-js

This is just my guess with limited information, as it usually occurs if we call them from outside the component.

In essence, you need to wrap the async-alpine component within the normal x-data component. This is because the component hasn't initialized yet, so $wire doesn't exist in the current state.

With Livewire v3 now stable, integrating async-alpine into livewire is much easier, as it now bundles alpinejs and exposes them together. See: https://livewire.laravel.com/docs/installation#manually-bundling-livewire-and-alpine

// resources/js/app.js
import './bootstrap';

import AsyncAlpine from 'async-alpine';
import { Livewire, Alpine } from '../../vendor/livewire/livewire/dist/livewire.esm';

AsyncAlpine.init(Alpine);
AsyncAlpine.alias((name) => import(`./components/${name}.module.js`));
AsyncAlpine.start();
Livewire.start();
// resources/js/components/counterlog.module.js
export default function counterlog({ number }) {
    return {
        number,
        init() {
            // will log returned @entangle() object,
            // but still able to get the initialValue from that object
            console.log(number)

            this.$watch('number', (value) => {
                console.log(value)
            });
        }
    }
}
<?php
//app/Livewire/Counter.php
namespace App\Livewire;

use Livewire\Component;

class Counter extends Component
{
    public $count = 1;

    public function increment()
    {
        $this->count++;
    }

    public function decrement()
    {
        $this->count--;
    }

    public function render()
    {
        return view('livewire.counter');
    }
}
{{--resources/views/livewire/counter.blade.php--}}
<div>
    <h1>{{ $count }}</h1>

    <div
        x-ignore
        ax-load
        x-data="counterlog({
            {{-- Use @entangle rather than $wire --}}
            number: @entangle('count'),
        })"
    >
        <span x-text="number"></span>
    </div>

    <button wire:click="increment">+</button>

    <button wire:click="decrement">-</button>
</div>
danharrin commented 9 months ago

https://github.com/filamentphp/filament heavily uses Async Alpine with Livewire, without issues. $wire works just fine, so I think this issue can be closed.

Accudio commented 9 months ago

Thank you both @iniznet and @danharrin. I'm going to mark this as closed in light of the recent comments.