Search code examples
laravellaravel-livewire

How do I know if an event was fired? Looks like it didn't


I have a UserShow component which shows the user's data (name, email, etc.) and also the actions he made in the site via relations (messages written, likes given, etc.). Now I want to allow user to change some of his data (name, email, etc.), so I wrote another component called UserEdit here is the form, validation, etc. It's working fine.

Since I'm using Livewire/Alpine I have some logic like

<div x-data="{ isEditing = @entangle('isEditing) }">
    <section x-show="!isEditing" />
        ...All user data...
        <button x-on:click="isEditing=true">
    <section>

    <section x-show="isEditing">
        <livewire:user.user-edit :user="$user" />
    </section>
</div>

So this works - it opens the component where the user will edit his data. In the component by the form's end, I have two buttons:

<div>
  <button type="submit">update</x-gui.button>
  <button type="button" wire:click="canceled">Cancel</button>
</div>

The canceled function in the component is:

public function canceled() {
  Log::info('Canceling Edit');
  $this->emitUp('canceled');
}

Now, in the parent element I have the listeners ans the function defined as:

protected $listeners = ['canceled' => 'restart'];

public function restart() {
  Log::info('canceled received');
}

When I click the cancel method in the component, I see the first log "Canceling Edit", but I don't see the "canceled received" message

Am I doing something wrong? How do I know if the "canceled" event is even being fired?


Solution

  • I found what happened, and it was a very strange behaivour, so it tooks ages to debug.

    The problem in this very specific component is that it was displaying all the messages inside a foreach, like:

    <div x-data="{ isEditing = @entangle('isEditing) }">
        <section x-show="!isEditing" />
            ...All user data... <=== PRECISELY HERE!!!
            <button x-on:click="isEditing=true">
        <section>
    
        <section x-show="isEditing">
            <livewire:user.user-edit :user="$user" />
        </section>
    </div>
    

    The all user data had a @foreach() that was rendering another component:

    @foreach($user->messages as $message)
        <livewire:message-card :message="$message" />
    @endforeach
    

    The problem was this livewire component wasn't being keyed, and this caused all kind of strange things to happen, chaging the line as below, solved the problem

    <livewire:message-card :message="$message" :key="$message->id" />
    

    So, the cautionary tale is: Always key your components inside a loop, even when they are just for displaying information, and not to be acted upon them