usernotnull / tall-toasts

A Toast notification library for the Laravel TALL stack. You can push notifications from the backend or frontend to render customizable toasts with almost zero footprint on the published CSS/JS šŸ”„šŸš€
MIT License
548 stars 32 forks source link

"->push()" not working on backend livewire component. #437

Closed marchershey closed 11 months ago

marchershey commented 1 year ago

So after the Livewire 3.0 update, ->push() no longer works on backend livewire components.

->pushOnNextPage() works perfectly fine... even on the frontend using Toast.success('A toast without a title also works') works as well, but the only way ->push() works inside a livewire component is if I remove the use WireToast trait, then it acts similarly to ->pushOnNextPage().

Here's my setup, maybe I'm missing something. If there is any other page I need to share, please let me know:

Alpine.plugin(ToastComponent);

Livewire.start();


- **base.blade.php**
```blade
<!DOCTYPE html>
<html lang="en" class="...">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>{{ config('app.name') }}</title>
    @toastScripts
    @vite(['resources/js/app.js', 'resources/css/app.css'])
    @livewireStyles
</head>

<body class="...">
    <livewire:toasts />

    <div>
        {{ $slot }}
    </div>

    @livewireScriptConfig
</body>

</html>

namespace ...;

use Illuminate\Contracts\View\View; use Livewire\Component; use Usernotnull\Toast\Concerns\WireToast;

class TestPageComponent extends Component { use WireToast;

/**
 * Return the Host Dashboard view
 *
 * @return View view
 */
public function render(): View
{
    return view('test-page-component');
}

public function testToast(): void
{
    toast()->success('This is a test toast.')->push();
}

}

marchershey commented 1 year ago

I've also customized the views a tad bit, so I'll post those as well. I do doubt that the changes I've made in the views are affecting it, but ya never know. I may be overlooking an issue. I did try to remove my custom views and use the default, but no luck.

- **includes/content.blade.php**
```blade
<div class="p-3 mx-4 my-4 mb-5 text-gray-800 bg-white border border-gray-300 rounded-lg shadow-2xl sm:mx-6" x-bind:class="{
    'bg-blue-50': toast.type === 'info',
    'bg-green-50': toast.type === 'success',
    'bg-yellow-50': toast.type === 'warning',
    'bg-red-50': toast.type === 'danger'
}">
    <div class="flex items-center space-x-3">
        <div>
            @include('tall-toasts::includes.icon')
        </div>
        <div class="w-full">
            <div class="text-base font-medium leading-5" x-html="toast.title" x-show="toast.title !== undefined" :class="{ 'mb-1': toast.title }"></div>
            <div class="text-sm leading-5" :class="toast.title ? 'text-muted' : ''" x-show="toast.message !== undefined" x-html="toast.message"></div>
        </div>
        <div>
            <svg class="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
                <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
            </svg>
        </div>
    </div>
    {{-- content --}}
    {{-- close --}}
</div>
cybernerdie commented 1 year ago

I also realized that when notifications are triggered from the backend, i need to manually refresh the page before it shows up, do you have same experience? @marchershey

usernotnull commented 1 year ago

I went through the last changes and noticed some livewire v3 breaking changes were not implemented in the latest contribution. I'm pushing v2.0.1 soon, let me know if it resolves the issue.

cybernerdie commented 1 year ago

Thanks for your prompt response, how soon will this push be made? @usernotnull

usernotnull commented 1 year ago

Unfortunately, the changes are deeper than I expected. The lifecycles are changed, leading to console error logs when the page loads. That's why the toasts work in certain circumstances (called from JS or backend) but not from a livewire component. I'll have to put a halt on this and label for help from the community as I have no time to delve into the livewire v3 changes.

marchershey commented 12 months ago

Any updates on this issue?

jacksontong commented 11 months ago

@usernotnull can you give us some insights how to fix this?

jacksontong commented 11 months ago

I'm not sure if this is a correct way to fix it but if I change dehydrate to rendered then it works (for unit test as well).

trait WireToast
{
    public function renderedWireToast(): void
    {
        if (! ToastManager::componentRendered()) {
            foreach (ToastManager::pull() ?? [] as $notification) {
                $this->dispatch(
                    'toast',
                    message: $notification['message'],
                    title: $notification['title'],
                    type: $notification['type'],
                    duration: $notification['duration'],
                );
            }
        }
    }
}

livewire(DocumentEditor::class)
    ->call('toastTest')
    ->assertDispatched(
        'toast',
        message: 'The document has been refreshed.',
        type: NotificationType::$success,
    );
usernotnull commented 11 months ago

I'm not sure if this is a correct way to fix it but if I change dehydrate to rendered then it works (for unit test as well).

trait WireToast
{
    public function renderedWireToast(): void
    {
        if (! ToastManager::componentRendered()) {
            foreach (ToastManager::pull() ?? [] as $notification) {
                $this->dispatch(
                    'toast',
                    message: $notification['message'],
                    title: $notification['title'],
                    type: $notification['type'],
                    duration: $notification['duration'],
                );
            }
        }
    }
}

livewire(DocumentEditor::class)
    ->call('toastTest')
    ->assertDispatched(
        'toast',
        message: 'The document has been refreshed.',
        type: NotificationType::$success,
    );

The Unit tests don't test the rendered state of the toast on the frontend.

@marchershey can you apply this fix and confirm it working?

usernotnull commented 11 months ago

I have tested the above and found it resolved the situation. Thanks @jacksontong! As this is a critical fix, I'll immediately tag a new release and wait for further feedback from the community.

Feel free to re-open.