Search code examples
javascriptlaraveltailwind-csslaravel-livewirealpine.js

Sending a message from Livewire eventDispatch to Alpine.js


I have a Tailwind alert that uses Livewire and Alpine.js to be displayed when a new project is saved with the event modal-closed

<div class="alert alert-success" style="display: none;" x-data="{ show : false }" x-show="show" x-on:close-modal.window="show = true">
    <p class="text-bold text-"><b>The project has been created successfully</b></p>
    <button @click="show = false" class="flex items-center p-1 ml-auto focus:outline-none">
        <svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" class="w-3 h-3 fill-current">
            <path d="M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z">
            </path>
        </svg>
    </button>
</div>

And I have a Livewire component that fires a modal-closed event.

public function save()
{
    // Validating the data
    $this->validate();

    $this->dispatchBrowserEvent('close-modal', ['message' => 'Project Created']);
}

What I want is to be able to display the message I'm sending with the dispatchBrowserEvent in the alert instead of having a fixed message "The project has been created successfully." Unfortunately, I haven't yet figured out how to do this.

I tried to use x-text="message" on the p tag, but it says

message is not defined.


Solution

  • You need to listen for that event with x-on:close-modal

    <div x-data="{ show : false, message: '' }" 
         x-show="show" 
         x-on:close-modal.window="show = true; message = $event.detail.message">
    
        <p x-text="message"></p>
    
    </div>
    
    

    Note: I did what you asked in your question. But I don't think you will see the text as you close the modal and the p is inside of it.


    If I can suggest an alternative approach is to send a second event

    $this->dispatchBrowserEvent('notify', ['message' => 'Project Created']);
    

    And have a re-usable toaster to display the notification using the same approach.
    (This is a simplistic example)

    <div x-data="{ show: false, message: '' }" 
         x-show="show" 
         x-on:notify.window="message = $event.detail.message"; setTimeout(() => { message = ''; show = false }, 2500)">
    
        <p x-text="message"></p>
    
    </div>