phplaravellaravel-8laravel-livewire

Livewire - Parent not listening to child $emit


I have these components in livewire and I want call a listener method in parent component

// index.blade.php
<div class="container">
    <livewire:layouts.header />

    <div class="row">
        <div class="col-12">
            <h3>
                Articles List
            </h3>

            @foreach($articles as $article)
                <livewire:articles.article-box :article="$article" />
            @endforeach
        </div>
    </div>
</div>
class Index extends Component {

    protected $listeners = [
        'forTest' => 'handleTest'
    ];

    public function handleTest() {
        Log::info('run HandleTest in Index Articles');

    }

    public function render() {
        return view('livewire.articles.index', [
            'articles' => Article::latest()->paginate(5)
        ]);
    }
}
// article-box.blade.php
<div>
    <h4>
        {{ $article->title }}
    </h4>
    <p>
        {{ $article->body }}
    </p>
    <div>
        like : {{ $article->like }}
        <button class="btn btn-danger btn-sm" wire:click="like">
            like
        </button>
    </div>
    <hr>
</div>
class ArticleBox extends Component {

    public Article $article;

    public function like() {
        //$this->article->increment('like');
        $this->emit('forTest');
    }

    public function render() {
        return view('livewire.articles.article-box');
    }
}
// header.blade.php
<div>
    <ul>
        <li>Home</li>
        <li>About</li>
    </ul>
</div>
class Header extends Component {

    protected $listeners = [
        'forTest' => 'myTest'
    ];

    public function myTest() {
        Log::info('run myTest in Header');
    }

    public function render() {
        return view('livewire.layouts.header');
    }
}

myTest and handleTest methods runned at first time but after that handleTest in Index Component method didn't workerd also after forTest() Event, the last article item comes to first item as you can see in images What' the problem?

before forTest() method after forTest() method


Solution

  • In Livewire 2 when you use nested components rendered in a loop you must provide a :wire:key attribute with an unique id, this allows Livewire to distinguish from a component to another:

    @foreach($articles as $article)
        <livewire:articles.article-box :article="$article" :wire:key="'article-' . $article->id"/>
    @endforeach
    

    See here for the details