首页 > 解决方案 > Laravel Livewire:Foreach 循环中的组件。按钮单击显示所有项目而不是单个项目

问题描述

我需要一些有关 Livewire Click 功能和将组件加载到 foreach 循环中的帮助。

当我单击播放按钮时,该组件显示在循环中的所有项目中。但我希望它只显示在单击按钮的这一项中。

问题截图

我希望有人可以帮助我解决这个问题。

提前谢谢了。

搜索-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

搜索视频.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');
    }
}

音频播放器.blade.php

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

音频播放器.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');
    }
}

标签: javascriptphplaravellaravel-livewire

解决方案


您需要能够确定 AudioPlayer 放置在哪个卡中。

首先在您的 AudioPlayer 组件中接受一个参数,该参数是视频的 ID - 将从您的搜索中传递。

在您的 AudioPlayer 组件中,添加一个mount()方法,您可以在其中接收一个可选参数$showVideoId。这意味着我们还必须将其声明为公共财产。

public $showVideoId;

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

接下来,我们需要从您的 Search 组件中传入它,

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

然后,更新您的openPlayer()方法以检查我们尝试打开的播放器是否与该播放器相同$showVideoId(或者null如果您没有传入该可选参数,因为在页面上使用此组件一次,而不是多次)。

这里我们检查是否$showVideoId为null,或者如果它不为null,它必须匹配$videoId

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

我注意到的另一件事,循环中的第一个元素,应该有一个wire:key

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

如果您的seach-video.blade.php视图以 开头@foreach,那么您应该将整个组件包装在<div>.


推荐阅读