Search code examples
phppaginationlaravel-livewirealpine.jslaravel-10

With Livewire pagination elements do not update when changing page


I'm passing a paginated collection of products from my Livewire class into my Livewire component and it mostly works fine. However when I change page via the pagination (e.g. go from page 1 to page 2) I find that the currently hidden elements do not update.

For example, when I go to page 2 the <p> containing the long description still shows the product->id from the corresponding product on page 1. However the <p> containing the short description updates fine.

What am I doing wrong?

App/Livewire/ProductList.php

<?php

namespace App\Livewire;

use Livewire\WithPagination;
use Livewire\Component;
use App\Models\Product;

class ProductList extends Component
{
    use WithPagination;

    public function render()
    {
        $products = Product::paginate(20);

        return view('livewire.product-list', [
            "products" => $products,
        ]);

    }
}

App/Resources/Views/Livewire/product-list.blade.php

<div class="grid grid-cols-4">
            @foreach ($products as $product)
                <div x-data="{expanded{{$product->id}}:false}" href="#">
                    <p x-show="!expanded{{$product->id}}">
                        {{$product->short_description}}
                    </p>
                    <a x-show="!expanded{{$product->id}}" x-on:click="expanded{{$product->id}}=true">
                        Read More                 
                    </a>
                    <p x-show="expanded{{$product->id}}">
                        {{$product->long_description}}
                    </p>
                    <a x-show="expanded{{$product->id}}" x-on:click="expanded{{$product->id}}=true">
                        Read Less                   
                    </a>
                </div>
            @endforeach  
        </div>
        <div id="productPagination">
            {{ $products->links() }}  
        </div>

Solution

  • Two things, first you need to ensure that your view contains only one root element. To achieve this I've wrapped the entire view in a div.

    Secondly, you need to provide a wire:key to the root element within the loop, and provide it a unique value.

    <div>
        <div class="grid grid-cols-4">
            @foreach ($products as $product)
                <div x-data="{expanded{{$product->id}}:false}" wire:key="product-{{ $product->id }}">
                    <p x-show="!expanded{{$product->id}}">
                        {{$product->short_description}}
                    </p>
                    <a x-show="!expanded{{$product->id}}" x-on:click="expanded{{$product->id}}=true">
                        Read More                 
                    </a>
                    <p x-show="expanded{{$product->id}}">
                        {{$product->long_description}}
                    </p>
                    <a x-show="expanded{{$product->id}}" x-on:click="expanded{{$product->id}}=true">
                        Read Less                   
                    </a>
                </div>
            @endforeach  
        </div>
        <div id="productPagination">
            {{ $products->links() }}  
        </div>
    </div>
    

    Also href is not a valid attribute on a div tag.