skip to Main Content

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 AppLivewire;

use LivewireWithPagination;
use LivewireComponent;
use AppModelsProduct;

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>

2

Answers


  1. It appears that Livewire updates the DOM but Alpine’s variables are misaligned, perhaps because they are dynamically composed (using the record id).

    A solution can be to introduce an id attribute in the main <div> of each row that varies on every update to let Alpine understand that it must reinitialize the object because the HTML is different

    <div id="id-{{ $product->id }}" x-data="{expanded{{ $product->id }}:false }" > 
       <!-- your html -->
    </div>
    
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search