Tuesday, May 14, 2024
 Popular · Latest · Hot · Upcoming
196
rated 0 times [  197] [ 1]  / answers: 1 / hits: 5171  / 3 Years ago, mon, september 6, 2021, 12:00:00

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


When I click the play button, the component 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');
}
}

More From » php

 Answers
2

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


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


In your AudioPlayer component, 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 component,


<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 component 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 component in a <div>.


[#909] Wednesday, September 1, 2021, 3 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
mckenna

Total Points: 445
Total Questions: 109
Total Answers: 109

Location: Virgin Islands (U.S.)
Member since Sun, May 16, 2021
3 Years ago
mckenna questions
;