【问题标题】:Laravel Livewire: Component in Foreach loop. Button Click shows on all items instead of Single itemLaravel Livewire:Foreach 循环中的组件。按钮单击显示所有项目而不是单个项目
【发布时间】:2021-11-03 22:18:31
【问题描述】:

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

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

Screenshot of issue

希望有人能帮我解决这个问题。

非常感谢。

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');
    }
}

【问题讨论】:

    标签: javascript php laravel laravel-livewire


    【解决方案1】:

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

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

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

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

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

    <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 开头,那么您应该将整个组件包装在&lt;div&gt; 中。

    【讨论】:

    • 非常感谢,对我帮助很大。
    猜你喜欢
    • 2017-06-02
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 2018-11-30
    • 2020-07-26
    • 1970-01-01
    相关资源
    最近更新 更多