javascript - Laravel Livewire: Component in Foreach loop. Button Click shows on all items instead of Single item - Stack Overflo

I need some help with the Livewire Click function and loading a ponent into a foreach loop.When I clic

I need some help with the Livewire Click function and loading a ponent into a foreach loop.

When I click the play button, the ponent is displayed in all items in the loop. But I would like that it is only displayed in this one item where the button was clicked.

Screenshot of issue

I hope someone can help me with this problem.

Many thanks in advance.

seach-video.blade.php

@foreach ($searchResults as $item)
    <div class="w-full mx-auto border rounded-md border-gray-300 shadow">
        ...
        <div class="px-4">
            <div class="mb-4 flex-1 space-y-4 py-1">
                <h2 class="text-xl font-semibold overflow-ellipsis overflow-hidden">{{ $item['title'] }}
                </h2>
                <div class="space-y-2">
                    <p>
                        ...
                    </p>
                </div>
            </div>
            <div class="flex flex-wrap py-4">

                <!-- Livewire Audio Player Component here -->
                <div class="w-full">
                   <livewire:audio-player :wire:key="$item['id']">
                </div>

                <div wire:click="openPlayer('{{ $item['id'] }}')"
                    class="cursor-pointer border rounded font-semibold bg-blue-300 border-blue-600 px-4 py-2 mr-2 text-blue-600">
                    Play</div>
                ...
            </div>
        </div>
    </div>
@endforeach

SearchVideo.php

class SearchVideo extends Component
{
    ....

    public function loadSearchResults()
    {
       ...
    }

    public function openPlayer($vid)
    {
        $this->emit('showPlayer', $vid)->to('audio-player');
    }

    public function closePlayer()
    {
        $this->emit('closePlayer')->to('audio-player');
    }

    public function render()
    {
        return view('livewire.search-video');
    }
}

audio-player.blade.php

<div>
    @isset($showPlayer)
      player here {{ $videoId }}
    @endif
</div>

AudioPlayer.php

class AudioPlayer extends Component
{
    public $showPlayer;
    public $videoId;

    protected $listeners = ['showPlayer' => 'openPlayer', 'closePlayer' => 'closePlayer'];

    public function openPlayer($vid)
    {
        $this->showPlayer = true;
        $this->videoId = $vid;
    }

    public function closePlayer()
    {
        unset($this->showPlayer);
    }

    public function hydrate()
    {
        $this->dispatchBrowserEvent('contentChanged');
    }

    public function render()
    {
        return view('livewire.audio-player');
    }
}

I need some help with the Livewire Click function and loading a ponent into a foreach loop.

When I click the play button, the ponent is displayed in all items in the loop. But I would like that it is only displayed in this one item where the button was clicked.

Screenshot of issue

I hope someone can help me with this problem.

Many thanks in advance.

seach-video.blade.php

@foreach ($searchResults as $item)
    <div class="w-full mx-auto border rounded-md border-gray-300 shadow">
        ...
        <div class="px-4">
            <div class="mb-4 flex-1 space-y-4 py-1">
                <h2 class="text-xl font-semibold overflow-ellipsis overflow-hidden">{{ $item['title'] }}
                </h2>
                <div class="space-y-2">
                    <p>
                        ...
                    </p>
                </div>
            </div>
            <div class="flex flex-wrap py-4">

                <!-- Livewire Audio Player Component here -->
                <div class="w-full">
                   <livewire:audio-player :wire:key="$item['id']">
                </div>

                <div wire:click="openPlayer('{{ $item['id'] }}')"
                    class="cursor-pointer border rounded font-semibold bg-blue-300 border-blue-600 px-4 py-2 mr-2 text-blue-600">
                    Play</div>
                ...
            </div>
        </div>
    </div>
@endforeach

SearchVideo.php

class SearchVideo extends Component
{
    ....

    public function loadSearchResults()
    {
       ...
    }

    public function openPlayer($vid)
    {
        $this->emit('showPlayer', $vid)->to('audio-player');
    }

    public function closePlayer()
    {
        $this->emit('closePlayer')->to('audio-player');
    }

    public function render()
    {
        return view('livewire.search-video');
    }
}

audio-player.blade.php

<div>
    @isset($showPlayer)
      player here {{ $videoId }}
    @endif
</div>

AudioPlayer.php

class AudioPlayer extends Component
{
    public $showPlayer;
    public $videoId;

    protected $listeners = ['showPlayer' => 'openPlayer', 'closePlayer' => 'closePlayer'];

    public function openPlayer($vid)
    {
        $this->showPlayer = true;
        $this->videoId = $vid;
    }

    public function closePlayer()
    {
        unset($this->showPlayer);
    }

    public function hydrate()
    {
        $this->dispatchBrowserEvent('contentChanged');
    }

    public function render()
    {
        return view('livewire.audio-player');
    }
}
Share Improve this question asked Sep 6, 2021 at 23:29 AndreAndre 131 silver badge3 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3

You need to be able to determine within which card the AudioPlayer is placed in.

Start by accepting a parameter in your AudioPlayer ponent, which is the ID of the video - which will be passed from your search.

In your AudioPlayer ponent, add a mount() method, where you can take in an optional parameter $showVideoId. This means we also have to declare it as a public property.

public $showVideoId;

public function mount($showVideoId = null) 
{
    $this->showVideoId = $showVideoId;
}

Next, we need to pass it in from your Search ponent,

<livewire:audio-player :showVideoId="$item['id']" :wire:key="$item['id']" />

Then, update your openPlayer() method to check if the player we are trying to open, is the same as that $showVideoId (or null if you don't pass in that optional parameter, for when using this ponent once on a page, instead of multiple times).

Here we check if $showVideoId is null, or if its not null, it must match the $videoId.

public function openPlayer($vid)
{
    $this->videoId = $vid;
    if ($this->showVideoId === null || $this->showVideoId === $this->videoId) {
        $this->showPlayer = true;
    }
}

Another thing I noticed, your first element in the loop, should have a wire:key on it.

<div class="w-full mx-auto border rounded-md border-gray-300 shadow" wire:key="search-{{ $loop->index }}">

And if your seach-video.blade.php view starts with the @foreach, then you should wrap the entire ponent in a <div>.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745302289a4621507.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信