laravellaravel-livewirelivewire-3

livewire wire:poll does not work correctly


I use Laravel 11 and livewire 3.5. I created a page with php artisan make:livewire TvDisplay, configured the controller and View, however when adding wire:poll to the components that need to be updated, the screen after 2.5s becomes completely white instead of updating the components

In this example, without wire:poll in the div, the page works perfectly by refreshing, but when adding wire:poll, instead of updating the component, when the update time comes, the screen becomes completely white

my controller looks like this:

<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\Ticket;
use Illuminate\Support\Facades\Log;

class TvDisplay extends Component
{
    public $calledTicket;
    public $upcomingTickets;

    protected $listeners = ['ticketUpdated' => 'updateTickets'];

    public function mount()
    {
        $this->updateTickets();
    }

    public function updateTickets()
    {   
        $this->calledTicket = Ticket::where('served', 1)->latest()->first();
        $this->upcomingTickets = Ticket::where('served', 0)->orderBy('created_at', 'asc')->take(10)->get();

    }

    public function render()
    {
        return view('livewire.tv-display');
    }
}

my view is like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TV Display</title>
    <style>
        body {
            background: url('storage/img/background.png') no-repeat center center fixed;
            background-size: cover;
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            overflow: hidden; /* Remove a barra de rolagem */
        }

        .container {
            color: white;
            height: 100vh;
            display: flex;
            flex-direction: row;
        }

        .left-panel {
            width: 28%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
            align-items: center;
            padding: 20px;
            text-align: center;
            margin-top: 90px; /* Ajuste conforme necessário */
        }

        .left-panel h1, .left-panel h2 {
            margin-top: 0;
        }

        .table-container {
            max-width: 100%;
            display: flex;
            flex-direction: column;
            align-items: center; /* Centraliza o conteúdo da tabela */
        }

        .video-panel {
            width: 66.67%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .video-panel video {
            width: 98%;
            height: auto;
            max-width: 100%;
        }

        table {
            width: 100%;
            margin-top: 20px;
            border-collapse: collapse;
            text-align: center; /* Centraliza o texto nas células */
        }

        th, td {
            padding: 10px;
            font-size: 2.1em; /* Aumentando o tamanho da fonte */
        }

        thead {
            background-color: #f2f2f279;
        }

        .called-ticket {
            width: 100%;
            height: 130px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            background-color:#f2f2f279; /* Retângulo branco com opacidade baixa */
            margin-bottom: 20px;
            font-size: 2.3em; /* Aumentando o tamanho da fonte */
            padding: 10px; /* Adicionando padding para melhor visualização */
        }

        .called-ticket h2 {
            margin: 0;
        }

        .called-ticket h3 {
            margin: 10px 0 0 0;
            font-size: 1.1em; /* Ajuste o tamanho da fonte conforme necessário */
        }
    </style>
</head>
<body>
<div class="container" >

    <!-- Divisão da Tabela e Texto -->
    <div class="left-panel">
        <div class="table-container">

            <h1>Senha chamada</h1>

            <div class="called-ticket" wire:poll>
                
                @if ($calledTicket)
                    
                    <h2>{{ $calledTicket->queue->name }} - {{ $calledTicket->sequential }}</h2>
                    @if ($calledTicket->user && $calledTicket->user->servicePost)
                        <h3>{{ $calledTicket->user->servicePost->name }}</h3>
                    @else
                        <h3>--</h3>
                    @endif
                @else
                    <h2>--</h2>
                    <h3>--</h3>
                @endif
            </div wire:poll>
            <table>
                <thead>
                    <tr>
                        <th>Fila</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach ($upcomingTickets as $ticket)
                        <tr>
                            <td >{{ $ticket->queue->name }} - {{ $ticket->sequential }}</td>
                        </tr>
                    @endforeach
                </tbody>
            </table>
            

        </div>
    </div>

    <!-- Divisão do Vídeo -->
    <div class="video-panel">
        <video autoplay muted loop>
            <source src="{{ asset('storage/tv/SPC.mp4') }}" type="video/mp4">
        </video>
    </div>

</div>
</body>
</html>

Solution

  • First off, both your div tags with wire:poll are not correctly closed.

    Secondly, you don't need 2 divs to call the same wire:poll; I assume you just want to call updateTickets, so for that you'd simply have a single wire:poll="updateTickets".

    Thirdly, your tr tags don't have a wire:key which makes DOM diffing for Livewire much harder. Add it like so: <tr wire:key="{{ $ticket->id }}">.